LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Are There Performance Drawbacks Between Using Named Queues vs Wired Queues?

I have an application with 12 separate state machines  running in (Asynchronous) loops. Eleven of the loops each has a data input queue, data output queue, and a message output queue. One of the 12 loops is specifically designed as the Queued Data Handler.  Meaning that all data transferred between loops passes through the Data Handler Loop and it is stored and re-packaged, and re-sent via the appropriate queue to meet the data requirements of each loop.  Thus there are 22 Data Queues attached to the Data Handler loop. Each loop also shares a single Message Queue that sends messages to the 1st loop (not the data handler loop) ... thus it is a multiple producer / single consumer queue.  In all there are a total of 33 queues used in the application.  Each queue transfers data clusters ranging in size from 30 - 500 Bytes with an average of about 300 Bytes. Loop rates vary from 10 mSec to 50 mSec.

 

As you can imagine using wires to connect all of the queues has become a wiring nightmare both alongside the queues and inside the already crowded state machines.  An alternative to wiring queues together is to name each queue and then use an [Obtain Queue/ Enqueue or Dequeue Element/ Release Queue] combination inside each loop where ever it is needed. This results in a much neater block diagram but I am worried that it might be causing a performance hit to the overall application due to the fact that everytime the combination is called a reference is both generated and then destroyed.

 

I have searched for information about drawbacks to using named queues but I have not found anything that addresses my concern.  Does anyone have any information or links to information  they can share regarding this matter?  Also is there a better way to use wired queues?  I tried putting all of the queue references into a bundle in order to pass around a single cluster wire (of queue references) but I have not figured out how to give each reference a unique name so using them is very tedious and prone to mistakes because they all share the same name (queue out).  Is there a way to rename a reference wire to a queue?

Jacob K
0 Kudos
Message 1 of 19
(4,705 Views)

Jacob_K wrote: 
[...]

I tried putting all of the queue references into a bundle in order to pass around a single cluster wire (of queue references) but I have not figured out how to give each reference a unique name so using them is very tedious and prone to mistakes because they all share the same name (queue out).  Is there a way to rename a reference wire to a queue?


Hello Jacob,

I can not comment on performance, but on naming.

You say you have a cluster with queue references. So Create a Type Definition of this cluster. Now in the Type Definition you can name each queue the way you want and then you can replace 'bundle'/'unbundle' nodes with 'bundle by name' / 'unbundle by name' nodes.

QueueNaming.png

UliB

0 Kudos
Message 2 of 19
(4,683 Views)

I often make a SubVI like this for each queue (the name input is optional):

Create queue reference.png

(The True case just wires through)

No wires dragging everywhere and I can make the icon of the SubVI be whatever identifies the queue name to me.

Creates the first time only, unless someone force-destroys it in which case it recreates itself the next time it's needed.

Message 3 of 19
(4,662 Views)

Hello Jacob,

I am also developing an application that uses several queues and met your same issue: Very similarly to what you did, I implemented a VI for each queue which I called "CmdSender", in which I pass the data, that contains the "obtain queue + enqueue element + release queue" sequence. Since some of the queues can grow quite big and some others needs to receive commands frequently, I questioned myself with your same doubt, so this is what I did: I restructured my CmdSenders making functional global variables of them, with a single queue reference created at the beginning (in parallel with the one kept active inside the VI that dequeues the commands) and stored through a shift register to be used for each enqueue command; after that, when the program needs to be closed, a global variable linked to the exit command goes into a boolean shift register to stop any other enqueue or queue creation in each CmdSender/FGV.

 

I can't asses how much exactly, but I assure you that performances were improved by this change.

 

Since the entire code involved is proprietary I'll post two commented screenshots instead of VI or snippets, hope they'll clarify what I tried to explain.

Download All
0 Kudos
Message 4 of 19
(4,652 Views)

Kyle97330 wrote:

Create queue reference.png

(The True case just wires through)


You have your cases flipped.  If the reference is "not a reference" (TRUE case) is where the Obtain Queue should be performed.

 

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.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 5 of 19
(4,635 Views)

We have dabbled with this for a while, using uniquely named queues (file name of queue functional global vi as queue name) and having actions for obtain, enqueue, enqueue at front, dequeue, flush, queue status etc. We recently upgraded this by making a typedef enum containing all queue names in the application. This way, once you have programmed the main queue control vi, you can add or remove queues from the application by updating the elements of the enum.

Best regards,

Jarle Ekanger, MSc, PhD, CLD
Flow Design Bureau AS

- "The resistance of wires in LabVIEW is not dependent on their length."
0 Kudos
Message 6 of 19
(4,629 Views)

Thank you for the suggestions thus far.  I have built 2 simple VIs to test my theory of performance between the two methods.  This has shown a performance difference that Wired Queues are roughly 10x faster than standard Named Queue combinations. 

 

Named Queues Example.pngWired Queues Example.png

 

I am interested in the suggested method to create a FGV with each reference but it is my understanding that every time the Obtain Queue vi is called a new reference is created regardless of whether or not the last reference was destroyed.  Thus if I just package the Obtain Queue as @crossrulz and @kyle97330 have discussed would that not lead to the same memory leak?  Or am I missing something?

 

I also tried this method here:

Named FGV Ref Queue Example.png

And the performance results were more than 100x worse than before.  The problem lies in the fact that you now have two seperate loops relying on access to a single FGV REF (sub vi). Am I doing something wrong here?  Should the same non-reentrant sub vi be used in both loops? The performance hit is a result of having to add timing to the loops so that Labview does not return Error 1 which seems indicative of mush slower performance.  Thanks for your continued suggestions.

Jacob K
0 Kudos
Message 7 of 19
(4,589 Views)

if you use a shift register you must use the non-reentrant setting. If you make a FGV or similar that obtains the queue by name you can set the vi to be reentrant or pre-allocated clone reentrant. just make sure you call an obtain to initialize the named queue, then whenever you use the queue you to obtain-operation-release.

Best regards,

Jarle Ekanger, MSc, PhD, CLD
Flow Design Bureau AS

- "The resistance of wires in LabVIEW is not dependent on their length."
Message 8 of 19
(4,584 Views)

Jacob_K ha scritto:

I am interested in the suggested method to create a FGV with each reference but it is my understanding that every time the Obtain Queue vi is called a new reference is created regardless of whether or not the last reference was destroyed.  Thus if I just package the Obtain Queue as @crossrulz and @kyle97330 have discussed would that not lead to the same memory leak?  Or am I missing something?


Supposing you're referring to my post in the quoted part, the code (in particular through first auxiliary boolean stored in the shift register) is structured so that the reference is created at the very first call of the subVI in the whole program (the CmdSender subVI is non-reentrant) and re-created again only in the case of its destruction is required but the program is not closed (in my case, this happens just in a rare and particular situation). Therefore what you say is correct, but it is programmatically prevented from happening.

0 Kudos
Message 9 of 19
(4,583 Views)

Jacob_K wrote:

I am interested in the suggested method to create a FGV with each reference but it is my understanding that every time the Obtain Queue vi is called a new reference is created regardless of whether or not the last reference was destroyed.  Thus if I just package the Obtain Queue as @crossrulz and @kyle97330 have discussed would that not lead to the same memory leak?  Or am I missing something?


In my setup, only the loop that reads from the queue performs the Obtain Queue part of the Action Engine.  It is also responsible for the Close action.  So the queue is not constantly being re-obtained.  It is only obtained once when the reading starts up.  I then use that reference inside of the Action Engine when sending messages.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 10 of 19
(4,569 Views)