wxpython and asyncio

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

wxpython and asyncio

Christian Bodt
Hi,

I have written this code to make wxpython work with python 3 asyncio:

https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9

What do you think about it?
Would anyone have some comments or suggestions to fix issues and/or improve performance?

Thanks,
Christian



--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
Hi Christian,

I tried running the sample code and couldn't get it to work (not on my Mac at least).

I first had to add the missing import statements to the example app.
    import wx
    from wxasyncapp import WxAsyncApp

Clicking the button does nothing (well nothing prints).

I made the button callback a standard non-async function and used self.Bind() and it works ok (i.e. it printed text to console).
BTW, I'd suggest reordering the parameters of AsyncBind to match wx Bind, just for consistency.

I tried creating another async task (outside of wx) that just printed some text every second.   It only runs once because as soon as the wx.MainLoop runs it blocks forever and doesn't give any other asyncio tasks to run :(

When I first played with wx and asyncio a while back, I had to run the asyncio loop (one iteration) from the wxIdle event.  There are some posts to show how I and others have done this.  My feeling was the asyncio apps didn't run very fast, and I was hoping your work might have improved things (maybe it's just the way my apps worked?).  I was hoping your work may have improved things as running wx MainLoop from the asyncio loop would be my preferred architecture (if ony we could run just one iterration of the wx MainLoop).

Brendan.


On Saturday, 2 June 2018 01:11:54 UTC+10, Christian Bodt wrote:
Hi,

I have written this code to make wxpython work with python 3 asyncio:

<a href="https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;">https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9

What do you think about it?
Would anyone have some comments or suggestions to fix issues and/or improve performance?

Thanks,
Christian



--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
Hi Simon,

This is indeed an issue with MacOS as evtloop.Pending() always returns True there.
You can try with the file attached and it should work. 
Thanks also for your comment about parameter order, I will update it as well.

Christian

Le samedi 9 juin 2018 13:32:26 UTC+2, Brendan Simon a écrit :
Hi Christian,

I tried running the sample code and couldn't get it to work (not on my Mac at least).

I first had to add the missing import statements to the example app.
    import wx
    from wxasyncapp import WxAsyncApp

Clicking the button does nothing (well nothing prints).

I made the button callback a standard non-async function and used self.Bind() and it works ok (i.e. it printed text to console).
BTW, I'd suggest reorderin the parametgers of AsyncBind to match wx Bind, just for consistency.
 
I tried creating another async task (outside of wx) that just printed some text every second.   It only runs once because as soon as the wx.MainLoop runs it blocks forever and doesn't give any other asyncio tasks to run :(

When I first played with wx and asyncio a while back, I had to run the asyncio loop (one iteration) from the wxIdle event.  There are some posts to show how I and others have done this.  My feeling was the asyncio apps didn't run very fast, and I was hoping your work might have improved things (maybe it's just the way my apps worked?).  I was hoping your work may have improved things as running wx MainLoop from the asyncio loop would be my preferred architecture (if ony we could run just one iterration of the wx MainLoop).

Brendan.


On Saturday, 2 June 2018 01:11:54 UTC+10, Christian Bodt wrote:
Hi,

I have written this code to make wxpython work with python 3 asyncio:

<a href="https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;">https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9

What do you think about it?
Would anyone have some comments or suggestions to fix issues and/or improve performance?

Thanks,
Christian



--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

wx_async.py (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached

Le samedi 9 juin 2018 15:35:07 UTC+2, Christian Bodt a écrit :
Hi Simon,

This is indeed an issue with MacOS as evtloop.Pending() always returns True there.
You can try with the file attached and it should work. 
Thanks also for your comment about parameter order, I will update it as well.

Christian

Le samedi 9 juin 2018 13:32:26 UTC+2, Brendan Simon a écrit :
Hi Christian,

I tried running the sample code and couldn't get it to work (not on my Mac at least).

I first had to add the missing import statements to the example app.
    import wx
    from wxasyncapp import WxAsyncApp

Clicking the button does nothing (well nothing prints).

I made the button callback a standard non-async function and used self.Bind() and it works ok (i.e. it printed text to console).
BTW, I'd suggest reorderin the parametgers of AsyncBind to match wx Bind, just for consistency.
 
I tried creating another async task (outside of wx) that just printed some text every second.   It only runs once because as soon as the wx.MainLoop runs it blocks forever and doesn't give any other asyncio tasks to run :(

When I first played with wx and asyncio a while back, I had to run the asyncio loop (one iteration) from the wxIdle event.  There are some posts to show how I and others have done this.  My feeling was the asyncio apps didn't run very fast, and I was hoping your work might have improved things (maybe it's just the way my apps worked?).  I was hoping your work may have improved things as running wx MainLoop from the asyncio loop would be my preferred architecture (if ony we could run just one iterration of the wx MainLoop).

Brendan.


On Saturday, 2 June 2018 01:11:54 UTC+10, Christian Bodt wrote:
Hi,

I have written this code to make wxpython work with python 3 asyncio:

<a href="https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fmedium.com%2F%40sirk390%2Fi-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFhMT6wLPD-q15j7BVFVeZY-wSmLg&#39;;return true;">https://medium.com/@sirk390/i-have-written-a-piece-of-code-to-combine-wxpython-with-the-python-3-event-loop-7dcec383d0b9

What do you think about it?
Would anyone have some comments or suggestions to fix issues and/or improve performance?

Thanks,
Christian



--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

wxasync_test.py (17K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)?

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

This is great work.  I'm loving it !!

Ok ,so I tried running the tests on macOS and got the following errors.

2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
I tried `asyncio.sleep(0)` in the wxAysnc MainLoop, but it things the test app output got really slow.  Processing the wx Mainloop must be quite expensive (at a guess).

Tried with 0.001 (1ms) and 0.000001 (1us) and it worked ok with the simple test app (not sure if the sleep has that resolution).

Brendan.


On Monday, 11 June 2018 13:38:43 UTC+10, Brendan Simon wrote:
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)?

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

This is great work.  I'm loving it !!

Ok ,so I tried running the tests on macOS and got the following errors.

2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Tim Roberts
On Jun 10, 2018, at 9:02 PM, Brendan Simon <[hidden email]> wrote:

I tried `asyncio.sleep(0)` in the wxAysnc MainLoop, but it things the test app output got really slow.  Processing the wx Mainloop must be quite expensive (at a guess).

Tried with 0.001 (1ms) and 0.000001 (1us) and it worked ok with the simple test app (not sure if the sleep has that resolution).

Absolutely not.  It varies by platform, but on Windows, waking from "sleep" is only checked at scheduler intervals, which is 16ms.  This even applies to a sleep(0).
— 
Tim Roberts, [hidden email]
Providenza & Boekelheide, Inc.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
In reply to this post by Brendan Simon-3

Le lundi 11 juin 2018 05:38:43 UTC+2, Brendan Simon a écrit :
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)

Yes, is seems to run a bit slower. I expect that more or less, due to the extra asyncio EventLoop. 

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

I would expect the wx latency to be close to 0ms in normal conditions, and 5ms for the code I provided. But up to 20ms should be quite acceptable for GUI events. 
You can expect wx/GUI latency to go down when making the asyncio.sleep smaller, but it increases context switching and CPU overhead. 

On windows, wx uses WaitForMultipleObjects to wait for GUI events, but this different on every platform.
This call cannot be done in a background thread because there is one message loop per thread.
To make this code better, we would require an asynchroneous system call to wait for GUI messages (e.g. WaitForMultipleObjectsEx with a callback).  I have searched a lot but couldn't find it. Maybe using SetWindowsHookEx+GetMsgProc to hook the thread message loop? 

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

I would use asyncio functions when you event processing needs to use a database or a network connection or anything that is IO bound. You could use wx normal functions when you don't have that. (e.g. just do some local computation and display the result)
 
Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

To run a coroutine (an "async def" function) in the background yes, I call loop.create_task. The latency is the time between a wx.PostEvent, and resulting callback call (for wx.Bind) or between a wx.PostEvent, and start-time of the cooroutine (for AsyncBind)
 
This is great work.  I'm loving it !!

Thanks! 

Ok ,so I tried running the tests on macOS and got the following errors.

I had some errors myself like 'This program needs access to the screen. Please run with a Framework build of python.'.
I am not a mac expert, so I just modified the code to run it manually (not in a background process) and that worked for me. (Nb: I run in a background process because otherwise, I have issues with multiple wx.App instances. I will check if there is a good solution if I have time.)

 
2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
In reply to this post by Brendan Simon-3
If you put "asyncio.sleep(0)" it will use up all your CPU peeking wx messages which  is not so good :)

Note (also to Tim) that asyncio. sleep() it is not a real windows.Sleep: it will just give back control to the event loop. It only sleeps when there are no events to process, but will wakeup quickly if there are new events.


Le lundi 11 juin 2018 06:02:22 UTC+2, Brendan Simon a écrit :
I tried `asyncio.sleep(0)` in the wxAysnc MainLoop, but it things the test app output got really slow.  Processing the wx Mainloop must be quite expensive (at a guess).

Tried with 0.001 (1ms) and 0.000001 (1us) and it worked ok with the simple test app (not sure if the sleep has that resolution).

Brendan.


On Monday, 11 June 2018 13:38:43 UTC+10, Brendan Simon wrote:
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)?

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

This is great work.  I'm loving it !!

Ok ,so I tried running the tests on macOS and got the following errors.

2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Chris Barker - NOAA Federal
I have no idea about the details, but I recall past discussions about replacing the existing existing event loop.

So in theory, you could use the asyncio event loop for everything, rather than having two parallel event loops.

Maybe that would add a lot of complication for little gain, but I’m wondering if it’s been considered.

-CHB

Sent from my iPhone

On Jun 11, 2018, at 2:32 AM, Christian Bodt <[hidden email]> wrote:

If you put "asyncio.sleep(0)" it will use up all your CPU peeking wx messages which  is not so good :)

Note (also to Tim) that asyncio. sleep() it is not a real windows.Sleep: it will just give back control to the event loop. It only sleeps when there are no events to process, but will wakeup quickly if there are new events.


Le lundi 11 juin 2018 06:02:22 UTC+2, Brendan Simon a écrit :
I tried `asyncio.sleep(0)` in the wxAysnc MainLoop, but it things the test app output got really slow.  Processing the wx Mainloop must be quite expensive (at a guess).

Tried with 0.001 (1ms) and 0.000001 (1us) and it worked ok with the simple test app (not sure if the sleep has that resolution).

Brendan.


On Monday, 11 June 2018 13:38:43 UTC+10, Brendan Simon wrote:
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)?

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

This is great work.  I'm loving it !!

Ok ,so I tried running the tests on macOS and got the following errors.

2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
Yes, this is what I do, everything runs on top of asyncio.

The only problem remaining is that you have to do a lot of polling for GUI messages, which can cause latency + decreased performance.  

Under windows, I don't think it is possible to solve this without a new API Call. The equivalent of "MsgWaitForMultipleObjectsEx+QS_ALLPOSTMESSAGE" does not exist using a callback. You have RegisterWaitForSingleObject but not MsgRegisterWaitForSingleObject.

Le lundi 11 juin 2018 19:55:33 UTC+2, Chris Barker - NOAA Federal a écrit :
I have no idea about the details, but I recall past discussions about replacing the existing existing event loop.

So in theory, you could use the asyncio event loop for everything, rather than having two parallel event loops.

Maybe that would add a lot of complication for little gain, but I’m wondering if it’s been considered.

-CHB

Sent from my iPhone

On Jun 11, 2018, at 2:32 AM, Christian Bodt <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="3ed7HKhMAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">sir...@...> wrote:

If you put "asyncio.sleep(0)" it will use up all your CPU peeking wx messages which  is not so good :)

Note (also to Tim) that asyncio. sleep() it is not a real windows.Sleep: it will just give back control to the event loop. It only sleeps when there are no events to process, but will wakeup quickly if there are new events.


Le lundi 11 juin 2018 06:02:22 UTC+2, Brendan Simon a écrit :
I tried `asyncio.sleep(0)` in the wxAysnc MainLoop, but it things the test app output got really slow.  Processing the wx Mainloop must be quite expensive (at a guess).

Tried with 0.001 (1ms) and 0.000001 (1us) and it worked ok with the simple test app (not sure if the sleep has that resolution).

Brendan.


On Monday, 11 June 2018 13:38:43 UTC+10, Brendan Simon wrote:
From your test results I'm reading that the wxAsync + AsyncBind gives worse results than wx.App + Bind.  Is that correct?  Or only when fully stressed (max load)?

wxAsync + AsyncBind performs "better" under normal conditions (lightly loaded) as it has a lower latency (5ms v 10ms), and presumably that could be reduced (e.g. say to 1ms by calling asyncio.sleep(0.001) instead of asyncio.sleep(0.005).  Correct?  Is there a way to yield (let asycio get some CPU) without "sleeping", so that when asyncio is idle, wx can resume immediately?

With the current results, does it make sense that anything that is time critical should be implemented in asyncio functions and anything not time critical in wxPy functions?

Just so I'm not confusing myself, the AyscBind function creates asyncio tasks (and the tasks run in the asyncio loop).  Is that correct?  So, the latency is in processing the final resultant callback in the wx loop?  Correct?

This is great work.  I'm loving it !!

Ok ,so I tried running the tests on macOS and got the following errors.

2018-06-11 13:13:55.940 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'ClientCallsAuxiliary': Connection invalid
2018-06-11 13:13:55.944 Python[75758:1519611] +[NSXPCSharedListener endpointForReply:withListenerName:]: an error occurred while attempting to obtain endpoint for listener 'HostCallsAuxiliary': Connection invalid


Brendan.


On Monday, 11 June 2018 00:07:30 UTC+10, Christian Bodt wrote:
After testing more the performance (on a Core-i7-7700K  4.2Ghz), I found the following (If I am correctly testing):

Reference values:
   * wx.App + Bind will handle 92 000 msg/s at 10ms latency (Using wx.PostEvent, and just a little less using CallAfter)
   * The asyncio loop will handle  550 000 msg/s with 0ms latency.

For "wxAsyncApp + AsyncBind" tests:
   * Will handle 48 000 msg/s at 20ms latency 
   * Under normal conditions (not filling the queue) wxAsyncApp + AsyncBind will have 5ms latency (which is expected because of the 5ms asyncio.sleep)
   * When using both wx and asyncio will handle max 42 000 PostEvent msg/s at 23ms latency + 85 000 async msg/s at 11ms latency

It is similar on MacOS.

This looks very good already for most scenarios, but it would be nice to improve it even more obviously (asyncio has 550 000 msg/s with 0ms latency, so it could be a lot better).

See also my testing file attached


--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="3ed7HKhMAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">wxpython-user...@googlegroups.com.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
In reply to this post by Brendan Simon-3
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
BTW, is there an online source repo for this (github or the like) ?

On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
In reply to this post by Brendan Simon-3
What is really weird is that it works perfectly if I substitute `await asyncio.sleep()` with plain old `time.sleep()`

Is that right?  I would have thought the coroutine would not have yielded and blocked the wx GUI coro from running it's event loop and updating the GUI.

Am I misunderstanding how this all works?  Maybe it's a Mac thing ???  Still why does `await asyncio.sleep()` not work similarly to `time.sleep()`

Brendan.


On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
Maybe there is something else going on.  I removed the sleep entirely, and the progress dialog took 3 seconds to update.  It's like after every all to Update only gets processed once per processing of the wx coro.  Even that doesn't make sense, as it should take approx 500ms to complete, not ~3 seconds.

Brendan.


On Wednesday, 20 June 2018 22:44:11 UTC+10, Brendan Simon wrote:
What is really weird is that it works perfectly if I substitute `await asyncio.sleep()` with plain old `time.sleep()`

Is that right?  I would have thought the coroutine would not have yielded and blocked the wx GUI coro from running it's event loop and updating the GUI.

Am I misunderstanding how this all works?  Maybe it's a Mac thing ???  Still why does `await asyncio.sleep()` not work similarly to `time.sleep()`

Brendan.


On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
In reply to this post by Brendan Simon-3
Hi Simon,

Could you provide the code where you call AsyncBind to an event? What event do you bind? 
If I call async_progress_dialog using loop.create_task, it works correctly on windows (I didn't test on MaxOs):

 
    app = WxAsyncApp()
    message = "A simle progress dialog to show-off wx_async capbilities\n\n"
    dlg = wx.ProgressDialog( title="Async Progress Dialog",
                             message=message )
    async def async_progress_dialog():
        for i in range(101):
            msg = message + f"{i}%"
            dlg.Update( value=i, newmsg=msg )
            await asyncio.sleep(0.05)
    loop = get_event_loop()
    loop.create_task(async_progress_dialog())
    loop.run_until_complete(app.MainLoop())
   
Nb: there is no repo yet, I will create it and publish the link.

Christian


Le mercredi 20 juin 2018 14:16:34 UTC+2, Brendan Simon a écrit :
BTW, is there an online source repo for this (github or the like) ?

On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Brendan Simon-3
Here is the main test code (slightly modified version from your wx_async.py)

if __name__ == '__main__':
    class TestFrame(wx.Frame):
        def __init__(self, parent=None):
            super(TestFrame, self).__init__(parent)
            vbox = wx.BoxSizer(wx.VERTICAL)
            button1 =  wx.Button(self, label="Submit")
            vbox.Add(button1, 1, wx.EXPAND|wx.ALL)
            self.SetSizer(vbox)
            self.Layout()
            AsyncBind(wx.EVT_BUTTON, self.async_progress_dialog, button1)

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( "Async Progress Dialog", message )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( i, msg )
                #await asyncio.sleep(0.05)
                #time.sleep(0.01)
                #time.sleep(0.001)

Brendan.


On Wednesday, 20 June 2018 22:49:43 UTC+10, Christian Bodt wrote:

Could you provide the code where you call AsyncBind to an event? What event do you bind? 
If I call async_progress_dialog using loop.create_task, it works correctly on windows (I didn't test on MaxOs):

 
    app = WxAsyncApp()
    message = "A simle progress dialog to show-off wx_async capbilities\n\n"
    dlg = wx.ProgressDialog( title="Async Progress Dialog",
                             message=message )
    async def async_progress_dialog():
        for i in range(101):
            msg = message + f"{i}%"
            dlg.Update( value=i, newmsg=msg )
            await asyncio.sleep(0.05)
    loop = get_event_loop()
    loop.create_task(async_progress_dialog())
    loop.run_until_complete(app.MainLoop())
   
Nb: there is no repo yet, I will create it and publish the link.

Christian


Le mercredi 20 juin 2018 14:16:34 UTC+2, Brendan Simon a écrit :
BTW, is there an online source repo for this (github or the like) ?

On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wxpython and asyncio

Christian Bodt
Ok, I found the issue.

It was the evtloop.Dispatch() in my code that was blocking the eventloop for 1 sec.
I didn't see it in my performance tests because I didn't do an asyncio lacency test with few asyncio messages and no GUI messages
With evtloop.DispatchTimeout(0) it works.

Also, I created a repo here for it and fixed the issue:

    https://github.com/sirk390/wxasync

Christian


Le mercredi 20 juin 2018 15:39:13 UTC+2, Brendan Simon a écrit :
Here is the main test code (slightly modified version from your wx_async.py)

if __name__ == '__main__':
    class TestFrame(wx.Frame):
        def __init__(self, parent=None):
            super(TestFrame, self).__init__(parent)
            vbox = wx.BoxSizer(wx.VERTICAL)
            button1 =  wx.Button(self, label="Submit")
            vbox.Add(button1, 1, wx.EXPAND|wx.ALL)
            self.SetSizer(vbox)
            self.Layout()
            AsyncBind(wx.EVT_BUTTON, self.async_progress_dialog, button1)

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( "Async Progress Dialog", message )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( i, msg )
                #await asyncio.sleep(0.05)
                #time.sleep(0.01)
                #time.sleep(0.001)

Brendan.


On Wednesday, 20 June 2018 22:49:43 UTC+10, Christian Bodt wrote:

Could you provide the code where you call AsyncBind to an event? What event do you bind? 
If I call async_progress_dialog using loop.create_task, it works correctly on windows (I didn't test on MaxOs):

 
    app = WxAsyncApp()
    message = "A simle progress dialog to show-off wx_async capbilities\n\n"
    dlg = wx.ProgressDialog( title="Async Progress Dialog",
                             message=message )
    async def async_progress_dialog():
        for i in range(101):
            msg = message + f"{i}%"
            dlg.Update( value=i, newmsg=msg )
            await asyncio.sleep(0.05)
    loop = get_event_loop()
    loop.create_task(async_progress_dialog())
    loop.run_until_complete(app.MainLoop())
   
Nb: there is no repo yet, I will create it and publish the link.

Christian


Le mercredi 20 juin 2018 14:16:34 UTC+2, Brendan Simon a écrit :
BTW, is there an online source repo for this (github or the like) ?

On Wednesday, 20 June 2018 22:15:49 UTC+10, Brendan Simon wrote:
Hi Christian,

I modified the sample code to use wx.ProgressDialog in the async callabck.  It has a for loop that updates the progress dialog and does a small await sleep.

The progress dialog updates slowly (too slow), unless I move the mouse around.  Do you know what's going on here?

        async def async_progress_dialog(self, event):
            message = "A simle progress dialog to show-off wx_async capbilities\n\n"
            dlg = wx.ProgressDialog( title="Async Progress Dialog",
                                     message=message,
                                   )
            for i in range(100):
                msg = message + f"{i}%"
                dlg.Update( value=i, newmsg=msg )
                await asyncio.sleep(0.05)

Brendan.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.