Browsing Remote Tag Provider Excessively Slow

I have a project I’m basically duplicating but tweaking to have two gateways instead of one. One gateway collects the data and the other handles visualization. This works out so I’m effectively just changing the project’s tag provider to be a remote one hosted on the data collecting gateway (among other things). In this project, I tend to have a lot of dynamic components that use the tag structure to determine what needs to be shown on the component. This works fine on the original project, but this is causing really noticeable performance issues when I modify it to use a remote tag provider. Components often take 10-30s (or more) to show their structure and any useful information.

I can look at reducing the number of tag reads, but I see the same issue in the designer and the gateway - trying to browse the tag structure seems to consistently take a long time. Sometimes the designer won’t even open the tag provider properly, and it kind of gives up and reloads the tag browser window with the folders all closed so it doesn’t need to keep trying to browse the remote tag provider. The gateway can sometimes take a couple of minutes to browse a remote tag provider, yet at the same time when I test the remote server response I get successful responses in typically the 200-300ms range. I’m still in development, so I don’t even have that many tags in the remote tag provider yet (~300).

Is that response time expected? How can I improve the performance of browsing tags in a remote tag provider?

What version are you on? There were some performance improvements made back in 8.0.x I think, but other than that there’s not a “make it faster” setting you’re missing (we’d have that on by default, wouldn’t we?).

8.0.16. Are there any best practices for performance or anything like that?

You might get a free performance bump moving to 8.1.9.

Otherwise I think you’ll need to keep the remote calls to a minimum. Maybe a crude cache where possible by building and storing results in datasets so you don’t browse the same things over and over.

Is the remote provider on the same network or external or over a slow VPN connection or something?

edit: all VPN connections are slow, that was redundant.

Both gateways are running on our internal office network, with one VM hosted somewhere in the office and one on my laptop. I’m hardwired into the network and ping speeds between the VMs are about 5 or 6ms, so I don’t think it ought to be a connection issue.

I had this issue with another project that I circumvented by basically creating a tag provider that was a static copy of the remote tag provider that instead of querying the remote tag provider, queried the database to pull the latest information that got stored. It’s just a bit of a hassle to set up so I was kind of hoping that maybe I was missing something with the connection that could resolve this a bit more easily.

Just to confirm, it’s expected that a remote tag provider could take several seconds for a single call?

Any network call could take several seconds. It may also depend on if the Gateway Network connection between the gateway is being used for other purposes as well. But consistently taking several seconds for a single browse call does sound a little slow, if that's what is happening.

Nothing’s consistent with it, unfortunately. Sometimes a browse is under a second, other times the read times out (at which point I lose gateway connection despite having the designer running on the same VM as the gateway; errors shown below).

Message: Error loading tags underneath [<redacted>]
Time: Fri Aug 13 1:23:37PM
Severity: ERROR
Logger: com.inductiveautomation.ignition.designer.tags.tree.nodes.EditableProviderNode
Stack Trace: java.util.concurrent.ExecutionException: com.inductiveautomation.ignition.client.gateway_interface.GatewayException: Read timed out&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.CompletableFuture.reportGet(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.CompletableFuture.get(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.TagTreeNode.executeChildrenBrowse(TagTreeNode.java:142)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.TagProviderNode.executeChildrenBrowse(TagProviderNode.java:74)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.AbstractBrowseNode\$Loader.doRun(AbstractBrowseNode.java:511)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.AbstractBrowseNode\$Loader.run(AbstractBrowseNode.java:551)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.Executors\$RunnableAdapter.call(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.FutureTask.run(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.ThreadPoolExecutor\$Worker.run(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.lang.Thread.run(Unknown Source)&#13;<br>Caused by: com.inductiveautomation.ignition.client.gateway_interface.GatewayException: Read timed out&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.newGatewayException(GatewayInterface.java:351)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.getResponse(GatewayInterface.java:530)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.sendMessage(GatewayInterface.java:283)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.sendMessage(GatewayInterface.java:278)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.invoke(GatewayInterface.java:934)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.impl.GatewayTagInterface\$GatewayProviderProxy.browseAsync(GatewayTagInterface.java:281)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.browseAsync(ClientTagManagerImpl.java:171)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.TagTreeNode.executeChildrenBrowse(TagTreeNode.java:141)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;... 8 common frames omitted&#13;<br>Caused by: java.net.SocketTimeoutException: Read timed out&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.socketRead0(Native Method)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.socketRead(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.fill(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.read1(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.http.HttpClient.parseHTTP(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.HttpURLConnection.getResponseCode(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.getResponse(GatewayInterface.java:437)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;... 14 common frames omitted&#13;<br>
Message: Connection to Gateway lost, due to exception.
Time: Fri Aug 13 1:45:27PM
Severity: WARN
Logger: com.inductiveautomation.ignition.client.gateway_interface.GatewayConnectionManager
Stack Trace: com.inductiveautomation.ignition.client.gateway_interface.GatewayException: Read timed out&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.newGatewayException(GatewayInterface.java:351)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.getResponse(GatewayInterface.java:530)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.sendMessage(GatewayInterface.java:283)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.sendMessage(GatewayInterface.java:278)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.invoke(GatewayInterface.java:934)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.impl.GatewayTagInterface\$GatewayProviderProxy.browseAsync(GatewayTagInterface.java:281)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.impl.ClientTagManagerImpl.browseAsync(ClientTagManagerImpl.java:171)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.TagTreeNode.executeChildrenBrowse(TagTreeNode.java:141)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.TagProviderNode.executeChildrenBrowse(TagProviderNode.java:74)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.AbstractBrowseNode\$Loader.doRun(AbstractBrowseNode.java:511)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.tags.tree.node.AbstractBrowseNode\$Loader.run(AbstractBrowseNode.java:551)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.Executors\$RunnableAdapter.call(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.FutureTask.run(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.util.concurrent.ThreadPoolExecutor\$Worker.run(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.lang.Thread.run(Unknown Source)&#13;<br>Caused by: java.net.SocketTimeoutException: Read timed out&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.socketRead0(Native Method)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.socketRead(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.SocketInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.fill(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.read1(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.io.BufferedInputStream.read(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.http.HttpClient.parseHTTP(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at java.base/java.net.HttpURLConnection.getResponseCode(Unknown Source)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;at com.inductiveautomation.ignition.client.gateway_interface.GatewayInterface.getResponse(GatewayInterface.java:437)&#13;<br>&nbsp;&nbsp;&nbsp;&nbsp;... 14 common frames omitted&#13;<br>

Consider using a message handler in your source gateway to do the browsing, then cache the results in the remote gateway in a script module top-level object.