Execution speed comparison of system.tag.query / browse --> browse wins

I always wanted to compare these two functions to see which won, and spoiler alert, it's system.tag.browse by more than an order of magnitude! At least for my very small site and test case...

sampling execution count = 50
system.tag.browse = 15ms
system.tag.query = 206ms

Code
provider = 'default'
query = {
  "options": {
    "includeUdtMembers": True,
    "includeUdtDefinitions": False
  },
  "condition": {
    "tagType": "UdtInstance",
    "attributes": {
      "values": [],
      "requireAll": True
    },
    "properties": {
      "op": "Or",
      "conditions": [
        {
          "op": "And",
          "conditions": [
            {
              "prop": "typeId",
              "comp": "Equal",
              "value": "<Specific UDT Type>"
            }
          ]
        }
      ]
    }
  },
  "returnProperties": []
}

tests = 50
from java.lang.System import nanoTime as nt


def average_execution_time(func, num_executions):
    total_execution_time = 0

    for _ in range(num_executions):
        start_time = nt()
        func()  # Call the function passed as an argument
        end_time = nt()

        execution_time = end_time - start_time
        total_execution_time += execution_time

    # Calculate the average execution time
    average_time = total_execution_time / num_executions

    return average_time

def q():
	system.tag.query(provider, query)
def browse():
	system.tag.browse('[default]<Base Area folder to exclude _types_ folder>', filter={'recursive': True, 'tagType': 'UdtInstance', 'typeId': "<Specific UDT Type>"})

average_execution_time(q, 50)/1000000
average_execution_time(browse, 50)/1000000
Default Tag Provider Summary

Code: Ignition Tag Count in a project - #2 by nminchin

Tag summary for provider "default"

tagType: {'UdtInstance': 122, 'Folder': 126, 'AtomicTag': 1242}
valueSource: {'memory': 234, 'opc': 802, 'reference': 2, 'expr': 195, 'db': 9}
dataType: {'Float4': 2, 'Int2': 3, 'DataSet': 55, 'Float8': 206, 'Int4': 415, 'String': 47, 'Int8': 61, 'Document': 1, 'Boolean': 452}
tagGroup: {'Default': 1354, 'Alarm Summary': 39, 'ConfigTags_CMDPLCReset': 73, 'Value Change Triggers': 24}
eventScripts: {'eventScripts': 78}
historyEnabled: {'False': 1490}

6 Likes

Thanks for this writeup! Just including a note for others if they decide to test this as well, don't include a wildcard character (*) in the path (first argument) of the system.tag.browse() call, since it needs to be the starting folder for the search. This is in contrast to the "Tag Path" field of the Tag Report Tool, which does accept * as a wildcard.

If curious, my test results was roughly
.query = 522ms
.browse = 174ms

Note that my Ignition designer was remotely connected to my test site, which had over 20,000 tags. So, this is probably a "Your mileage may vary" situation, but interesting to explore more. I usually go with .query for the ease of setup, but I will have to give .browse a try again sometime.

I tried pretty much the same thing to test the speed of both functions, and came to the same conclusion: browse is much faster than query. It's not even close.

But then I tried running them out of a loop, just one call at once, and I noticed something:
browse's execution time is rather stable. I get around 0.08 secs. Sometimes it goes up to 0.1 secs, but it stays in that ballpark.
query, on the other hand, varies wildly. I can get results in 0.01 secs one time, and 0.3 secs on the next call. That's 30 times longer on the 2nd call !

I was kinda hoping to replace some browse calls with query, the added flexibility in the filtering would be helpful in some cases, but I guess I'll stick with it for now.

Use .query when you want to recurse into the tree. Use .browse() when you don't. Unless you want to grab a bunch of properties. Then using .query() is usually faster than .browse() followed by .readBlocking().

What do you mean by tree ?
The tag tree, or the 'property tree' of particular tags ?

My test was using a recursive browse, and it came out ahead.

The tag tree.

I find that surprising.

Yes, I guess query does remove the need to read the tags afterward to get their values...
This should probably be included in the test.

1 Like

I'm only discovering this function, I completely missed its introduction, so I have to experiment with it a bit, but...

What if I want to read tags in a UDT instance ? Or its parameters ? I can't find a way to do that with query.
Assuming I'll still have to use readBlocking to get their values, should I use query or browse to get the UDT instances paths ?

system.tag.query() is the fundamental backing of the Designer's Tag Report Tool. Use that to get a feel for how it works. Yes, it has settings for searching within UDT instances. That tool will also write the sample jython that corresponds to what you've set up.