Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ General ➜ Flushing output for world.Note

Flushing output for world.Note

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Graymane   USA  (14 posts)  Bio
Date Tue 24 Jun 2014 01:41 PM (UTC)
Message
I have a lua script where I want to run a long running operation and update the user as it progresses. So I have a loop and each iteration of the loop prints out progress.

...
for k in pairs (blah) do
print ("processing step " .. k)
...
end

The problem is that none of the print statements show up until the loop is done and I can't figure out a way to flush the output. I read that lua print is actually overridden by MushClient to do world.Note or the equivalent.

My question is, how can I write this loop to print out immediately?
Top

Posted by Fiendish   USA  (2,534 posts)  Bio   Global Moderator
Date Reply #1 on Tue 24 Jun 2014 02:33 PM (UTC)

Amended on Tue 24 Jun 2014 02:42 PM (UTC) by Fiendish

Message
http://www.gammon.com.au/scripts/function.php?name=Repaint

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Graymane   USA  (14 posts)  Bio
Date Reply #2 on Tue 24 Jun 2014 02:38 PM (UTC)
Message
Thanks! Worked like a charm.
Top

Posted by Fiendish   USA  (2,534 posts)  Bio   Global Moderator
Date Reply #3 on Tue 24 Jun 2014 02:42 PM (UTC)
Message
Though if you call Repaint too frequently you'll find that MUSHclient can slow down, because Repaint calls are expensive. I made a plugin that works around this.

https://code.google.com/p/aardwolfclientpackage/wiki/RepaintBuffer

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #4 on Tue 24 Jun 2014 09:48 PM (UTC)
Message
An alternative is to do SetStatus which I usually do for this sort of situation where you are keeping track of a lengthy operation. This should update immediately, although I have noticed that it may stop doing that if you lose focus on the output window.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #5 on Wed 25 Jun 2014 03:57 AM (UTC)
Message
I measured doing 1000 Repaint calls in 2.73 seconds on my PC, so you could reckon the overhead of doing a single Repaint would be around 3 mS.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #6 on Wed 25 Jun 2014 04:10 AM (UTC)

Amended on Wed 25 Jun 2014 04:11 AM (UTC) by Nick Gammon

Message
Fiendish's plugin (rather cleverly) defers the repainting until OnPluginTick is called which itself is every 40 mS (25 times a second). So the overhead of 3 mS is now only expended every 40 mS.

This gives a 25 FPS frame rate which is pretty acceptable as that is what TV broadcast frame rates are (roughly).

Using his plugin (example code below) the time for the loop has reduced to 0.445 seconds which is therefore an overhead of 0.445 mS per iteration rather than 2.73 mS, which is somewhat of an improvement.


start = utils.timer ()
for i = 1, 1000 do
  print (i)
  BroadcastPlugin (999, "repaint")
end 
finish = utils.timer ()
print (finish - start, "seconds")

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Fiendish   USA  (2,534 posts)  Bio   Global Moderator
Date Reply #7 on Wed 25 Jun 2014 04:30 AM (UTC)

Amended on Wed 25 Jun 2014 04:42 AM (UTC) by Fiendish

Message
Well...it will give between 10 and 25 fps, depending on load. OnPluginTick only gets called when the system isn't busy doing other things so the plugin forces a paint sometimes.

Now that I think about it more, I wonder if I don't need to change this to use timers instead. Calls made within 0.1 seconds of the last effective one will still get starved out by activity (blocking OnPluginTick) if no calls occur subsequently.

I think I recall timers being a bit slower though. Dilemma.

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Fiendish   USA  (2,534 posts)  Bio   Global Moderator
Date Reply #8 on Wed 25 Jun 2014 04:51 AM (UTC)
Message
If Repaint just naturally buffered calls internally, of course, all the overhead of custom timer creation and plugin callbacks would go away. Not to mention the plugintick spam in trace outputs.

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #9 on Wed 25 Jun 2014 08:21 PM (UTC)
Message
I tried that just now and it didn't work. Which didn't totally surprise me, as I was confused about how the Repaint_Buffer plugin worked anyway.

The reason for my confusion was that you are in a tight Lua loop (in this case) and there is no reason for timers to be processed until the Lua code exits back to the C++ main loop.

However then I noticed this:


function OnPluginBroadcast (msg, id, name, text)
   if (msg == 999 and text == "repaint") then
      repaint_on_tick = true
      if (utils.timer() - last_repaint_time > .1) then
         repaint_on_tick = false        
         Repaint()
         last_repaint_time = utils.timer()
      end
   end
end


The check for the timer right there is what makes it work.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Fiendish   USA  (2,534 posts)  Bio   Global Moderator
Date Reply #10 on Thu 26 Jun 2014 03:08 AM (UTC)

Amended on Thu 26 Jun 2014 03:10 AM (UTC) by Fiendish

Message
What did you try?

Quote:
The reason for my confusion was that you are in a tight Lua loop (in this case) and there is no reason for timers to be processed until the Lua code exits back to the C++ main loop.
I'm talking about leaving in this part
 if (utils.timer() - last_repaint_time > .1) then
because it's still necessary but replacing the
repaint_on_tick = true/false
with 0.1 second one-shot temporary timer set/unset calls and then removing the OnPluginTick callback.

Anyway, as you say the timer wouldn't get processed until later, so this wouldn't help. I guess nothing can be done about that edge case.

https://github.com/fiendish/aardwolfclientpackage
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #11 on Thu 26 Jun 2014 04:02 AM (UTC)
Message
Fiendish said:

What did you try?


To replicate what your plugin did in code, basically. It set a flag in Repaint and that flag was tested at the time it does the OnPluginTick stuff. However since that depended on a system timer firing and being noticed, it wasn't since the Lua script did not terminate and let Windows feed my code more events. So it did nothing basically.

The only reason your plugin works in a CPU loop (ie a lot of scripting) is your test for elapsed time.

Quote:

I'm talking about leaving in this part

...

because it's still necessary but replacing the

...

with 0.1 second one-shot temporary timer set/unset calls and then removing the OnPluginTick callback.


Unfortunately that wouldn't do much. I would have to basically replicate the entire plugin in code, including that test for time. You may as well just leave the plugin there.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


27,694 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.