08-26-2017 10:50 AM
I randomly came across an old AF conversation where the problem turned out to be a slow display update causing a Queue to backup with messages. I realized that the usual solution to such problems, that I always use, isn’t available in the AF, so I thought I would propose adding it. See the modified Actor:Actor Core.vi below.
The basic idea is that you never do expensive display updates in handling a message. Instead you record the information contained and the fact that the display needs updating. You use a zero timeout to trigger a “Queue Empty” action to actually do the expensive display work. That way, if the Queue contains several messages that all require a display update, the update only happens once. This is particularly valuable if you use fast-firing events like “Mouse Move” or “Cursor Move”, that can easily arrive faster than the display can be updated.
After calling “Queue Empty”, a timeout value of -1 (no timeout) is feedback to the Receive Message subVI, meaning that “Queue Empty” is only called again after another message.
08-28-2017 10:10 AM
That's an interesting idea. Could be added without breaking any existing uses of the AF.
We'd have to document not to use it for initializing your actor. Some people might assume they'll always get an empty queue message right at the start, because they'd get one most of the time, but every once in a while, someone would send a message fast enough.
We could remedy that by changing the initialization value from 0 to -1 and passing 0 in any frame that does get a message. Then there's no up-front empty queue call. Would that change cause a problem for any designs that want to use this pattern?
08-28-2017 10:19 AM
Would then consider changing the name of the method to something like "Finish Message Burst."
There is a small performance hit for those who get messages on a rapid-fire-but-not-quite-continuous basis, and it impacts actors all over. To avoid that, should this be an opt-in setting of actors configured on the base class? Just a Boolean that makes the message received cases still return -1 timeout instead of 0?
08-30-2017 02:59 PM
Hi AQ,
I'm on holiday this week so I can't respond often, but what you suggest sounds fine.
10-20-2017 12:53 PM
@AristosQueue (NI) wrote:
We'd have to document not to use it for initializing your actor. Some people might assume they'll always get an empty queue message right at the start, because they'd get one most of the time, but every once in a while, someone would send a message fast enough.
We could remedy that by changing the initialization value from 0 to -1 and passing 0 in any frame that does get a message. Then there's no up-front empty queue call. Would that change cause a problem for any designs that want to use this pattern?
Actually, it might be better to put an additional call to "Queue Empty" just before the message-handling loop. Then one could put initialization code inside without any race condition.
05-10-2022 09:43 PM
Would putting a value in the Actor's private data allow configuring the timespan for inactivity?
That might help in the case described with frequent but non-continuous messages, although it does then have the same issue as relying on the timeout event case in the EvStr (i.e., might never fire, whereas with 0 it would require a continuously backed up queue to not fire).
Are there particular performance issues with non-zero, non-negative timeout values? (I'm thinking about blocking behaviours, but maybe not relevant)
05-11-2022 03:05 AM - edited 05-11-2022 03:06 AM
@cbutcher wrote:
Would putting a value in the Actor's private data allow configuring the timespan for inactivity?
That might help in the case described with frequent but non-continuous messages, although it does then have the same issue as relying on the timeout event case in the EvStr (i.e., might never fire, whereas with 0 it would require a continuously backed up queue to not fire).
Are there particular performance issues with non-zero, non-negative timeout values? (I'm thinking about blocking behaviours, but maybe not relevant)
From my use of this technique I would recommend the timeout after any message ALWAYS be zero, however the timeout after handling the timeout case can be:
In my example code above, I only implemented the first case, but one could have the "Queue Empty" method output the Timeout (with a default of -1) so Users can do all three.
BTW, if your actor can't ever get its Queue empty (and fire a Timeout=0 case) then it is close to failure regardless of what you do (as it is producing messages faster than they can be handled).