02-01-2018 11:54 PM
wrote:
wrote:
I don't see anything inherently wrong with what you described. Unbundling will have very very little impact on your performance. You will have much bigger things to look at if performance becomes an issue.
I'd be pretty surprised if the compiler didn't just optimize this out. The value will never change once the application starts and creates the reference. I'd guess it is smart enough to see this and just access the reference each time without going to unbundle to get the reference.
But, if it doesn't, it's a minimal thing.
Adding the bundles (especially using by name) allows for easier to read code. You can unbundle the name to self document your code as you go.
This is one of my main self-documenting strategies. Doing this, I rarely need a wire label unless the wire is long.
02-02-2018 04:06 AM - edited 02-02-2018 04:07 AM
wrote:
To avoid this, I'm considering bundling the queues' wires together and feeding the bundle into each loop, the loops can then unbundle the queues they need, when they need them.
I'm a little worried that this may have unexpected effects on the data flow. I don't think it should be a problem as the queue wires are refnums. So while the queues themselves are changing, the refnums aren't, and all should be fine?
Keep your bundle in a shift register and you can keep by-value data in it as well. Using a cluster in a shift register is, I would say, the standard way organize information in loops that need a lot of information. Use unbundle-by-name and good naming and subclustering and you'll have much clearer code and never accidentally wire the wrong thing. I learned this good practice long ago form the JKI statemachine, so you could look to that for an example.
Unbundling, BTW, generally has no performance impact whatsoever over separate wires. In the compiled code it is just an access by pointer. With a cluster of just refnums you don't need the shift register (but it doesn't hurt), but it is still no performance cost. It is faster than using a Global/Local/Action-Engine (not that those other techniques aren't relatively fast). A bigger advantage over those other techniques is that it cleans up the block diagram wiring without hiding anything or introducing global access. You can still follow the wires to see what interacts with what.
02-02-2018 04:42 AM - edited 02-02-2018 04:43 AM
The bundle / unbundle Queue technique works without a hitch, and as mentioned previously, the action engine is also a valid approach.
I have also often seen people holding ALL of their Queue refs in a giant cluster in an action engine - this makes me sad.
It works, but in a large project where there are multiple enqueuers it can be almost impossible to figure out the locations of all enqueuers for a particular queue.
Not a problem for the developer, but this can be infuriating for anyone maintaining your code in the future.
If you do you the action engine approach it makes far more sense to have one subVI per queue reference. Then if you ever need to find the enqueuers you can click the action engine VI in the project and "Find all". Just my $0.02.
0xDEAD
02-02-2018 05:44 AM
wrote:
If you do you the action engine approach it makes far more sense to have one subVI per queue reference. Then if you ever need to find the enqueuers you can click the action engine VI in the project and "Find all".
I actually go a step further. I have a library for each queue and make the AE private. I then have public VIs that can build up the messages that the dequeuer can process and then use the AE to send the message. The dequeuer also tends to be part of this library so that it can do the Initialize action and have the queue reference directly. So with this, the other loops just call whichever message VI they need and wire up the already defined parameters. If you want to figure out who is sending said message, you just do the search for that VI being called.
02-02-2018 07:25 AM
wrote:
wrote:
If you do you the action engine approach it makes far more sense to have one subVI per queue reference. Then if you ever need to find the enqueuers you can click the action engine VI in the project and "Find all".
I actually go a step further. I have a library for each queue and make the AE private. I then have public VIs that can build up the messages that the dequeuer can process and then use the AE to send the message. The dequeuer also tends to be part of this library so that it can do the Initialize action and have the queue reference directly. So with this, the other loops just call whichever message VI they need and wire up the already defined parameters. If you want to figure out who is sending said message, you just do the search for that VI being called.
That's some nice LOOP, Light Object Oriented Principle. 😄 Nice solution though.
/Y
02-02-2018 07:56 AM
While some may think my middle name is Action Engine I do not do the actual queue and dequeuing IN the AE.
I have used AE's the share the queue refs but once I get the ref the AE is no longer used. That way (provided I am not using fixed size queues) I do not have threads blocking each other... unless there is a reason I need them to block.
re: the original Q...
I agree the unbundle reduces to the equivalent of a pointer into a structure and there is little CPU required for that.
Ben
02-02-2018 12:59 PM
wrote:That's some nice LOOP, Light Object Oriented Principle. 😄
Yes, it is. This thought process actually helped me to dive into OOP. But I still prefer not adding the class overhead if it is not necessary.
02-02-2018 04:16 PM
I create wrapper VIs for all the actions in any AEs I use, and its one of my pet peeves when others don't. It makes the code cleaner, and much easier to debug when you are trying to figure out which actions are called where.