Multiple single lines of System.tag.readblocking versus utilizing the array

Hello, I was wondering if anyone knows the impact of the 2 different scenarios:

  1. Repeating the below say 50 times, each tag getting its own read blocking logic
if (system.tag.readBlocking(['tag path'])[0].value
#Preform logic
  1. The proper way, putting all the tag paths in an array, executing a single readBlocking statement

Specifically, will the first scenario take longer to execute? Example 5s instead of 0.2s, or any other potential impacts?

(1) is dramatically slower than (2). 10x slower or more. If in a Vision client, it can even be hundreds or thousands of times slower.

1 Like

Thanks pturmel, thats what I was expecting, however the speed difference is pretty crazy.

In terms of readability, when using multiple tags in a readBlocking array, the result isn't always the most readable, since you have to remember array index's or do re-buffering of the results.

I am trying to figure out what might be acceptable or not, do you have any time estimates? Such as 10 readblocking is 1s, etc. In my case my script will execute once per minute, so I have some flexibility when it comes to readability/modularity vs delays depending on how bad it may be

1 Like

If at all possible always read as an array.

Consider building a list of tags and then using the .indexOf to find the index based on the tag name.

1 Like

Just use one readblocking to get everything you will need in your script. Use python tuple unpacking to assign finished results to local variable names in a one-liner. Use those variable names where needed in your script. Use a project library script to cache your list of tag paths. Something like this:

# Imports up here
logger = system.util.getLogger(system.util.getProjectName() + "." + __name__)
somePaths = ['path/to/tagA', 'path/to/tagB', 'path/to/tagC'] + ['other/numbered/tag%02d' % i for i in range(20)]

def someTimerEvent():
	qvList = system.tag.readBlocking(somePaths)
	if all([qv.quality.good for qv in qvList]):
		vList = [qv.value for qv in qvList]
		tagA, tagB, tagC = vList[:3]
		others = vList[3:]
		# Do stuff with tagA, tagB, tagC, and others.
		# Report bad quality
		logger.warnf("Bad tags in someTimerEvent: %s", repr(qvList))
1 Like

Thanks all, the impact and importance of this is very enlightening

Tuple unpacking is great and I take that approach very often, but on occasion if you're working with many tags at once, then I like to use the following functions to read tag values into a dictionary and write them back from a dictionary.

def createTagValueDict(tagPaths,parentPath):
	return {tagName[len(parentPath):]:qValue.value for tagName,qValue in zip(tagPaths,system.tag.readBlocking([path for path in tagPaths]))}
def writeTagValueDict(values,parentPath):
	parentPath = parentPath if parentPath[-1:] == '/' else parentPath + '/'
	writePaths, writeValues = [list(x) for x in zip(*values.items())]
	longWritePaths = [parentPath + path for path in writePaths]
	return system.tag.writeBlocking(longWritePaths,writeValues)

Then you can reference the value by the key something like tagValues['YourTagName']

Somewhere on the forum I have post where I benchmarked readBlocking() can't find it at the moment.

1 Like