07-21-2017 10:21 AM - edited 07-21-2017 10:36 AM
I made a simple error in my last post. I left a Destroy Queue in place. After removing it there was much better performance. After testing all of the suggestions here are my findings.
Wired Queues have the best performance and all other methods will be measured against using only wires to pass a single reference.
Performance = 1x
Named Queue with (Obtain/ Enqueue/ Destroy) combo where needed
Peformance = 10x
Named Queue with Non-Rentrant FGV Sub-VI
Performance = 4.5x
Named Queue with Pre-Allocated FGV Sub-VI
Performance = 2.2x
Hybrid Named Queue with Pre-Allocated FGV Sub-VI Wired inside each loop. Basically this method cleans up all the wires between various loops and has very little performance overhead.
Performance = 1.06x
All things considered, I will end up using the Hybrid method. It allows for a clean block diagram and has very close performance to using native wires.
Thanks for all the suggestions.
07-21-2017 10:29 AM
How are you determining "performance"? Your first and last setup are pretty much identical, so if you are seeing a 20% "performance" difference I don't think your measure is accurate.
07-21-2017 10:33 AM
@crossrulz wrote:
Personally, I take the Action Engine further. I have 3 actions it can perform: Get Reference (does the Obtain if reference is invalid), Send, Close (destroys the queue). If you want to go full out, you have a wrapper VI for the Send action and have the actual AE private to the module that reads the queue. This does require a library for each module. But the module that reads from the queue maintains it (obtain at start, release when done, sit there and read in the middle). And for somebody to send a message, they just call that wrapper VI mentioned earlier. No opening and closing of references. No names needed.
The first time I did this I made a 4th case as well - Dequeue Element. It didn't take long to find that everything locks up when one VI has already called Dequeue and no one can send any messages because it is non re-entrant 😄
07-21-2017 10:33 AM
This post has nothing to do about queue performance but may give you something to think about for your next project.
I used to use multiple queues like yourself, but got tired of multiple wires and worrying about destroying references, etc. I switched from queues to user events and have not looked back. User Events allow me to have 1 wire/reference reach any loop, subVI, etc, in my program. I use a combination of the JKI State Machine and an architecture similar to
http://forums.ni.com/t5/Example-Program-Drafts/Message-Bus-Architecture-An-Intro/ta-p/3512280
For more information regarding User Events see
https://github.com/JackDunaway/LabVIEW-User-Events-Tips-Tricks-and-Sundry
mcduff
07-21-2017 10:39 AM - edited 07-21-2017 10:42 AM
@gregoryj ... I made a wrong calculation. My actual performance difference is 1.06x. I have updated my post to reflect this. The measurements were made with very simple vis in order to get a relative idea of performance. In this case I only ran the VI for 1.17 seconds. If this were in a real application running for a long time the performance difference would approach zero.
07-21-2017 01:08 PM
Is the Msg Ref VI similar to what Kyle97330 posted, or is it different? If so, would you mind posting it saved for LV14?
07-21-2017 01:36 PM
I read that the named queues are a security risk and/or an possible accident waiting to happen if you have a typo.
Getting and releasing requires time.
Another approach would use a re-entrant VI that caches the queue ref on first call and subsequent calls to the re-entrant VI returns the cached queue ref. On first call the queue, is obtained from an Action Engine.
Another idea is to use the Variant attribute feature and store the queue refs as attributes of a variant in an AE.
I have written apps with hundreds of queues and the wired form has worked well for me.
Ben
07-21-2017 02:42 PM
@Jacob_K wrote:
All things considered, I will end up using the Hybrid method. It allows for a clean block diagram and has very close performance to using native wires.
You didn't try my method, where the sender does not even see the reference wire. So if you want a clean diagram, my method replaces the Enqueue with the bonus that the get reference is not needed.
06-30-2018 05:22 PM
crossrulz method is best imho. It allows the use of named Queues anywhere, without obtaining the queue each time the VI is called. That way the named queue is obtained only in the init method, or if reference is invalid. The rest of the time the wire reference is used, maintaining best performance. I use similar methods personally.