Replies: 2 comments 6 replies
-
Looks very interesting! Another thing, unrelated to this feature I guess, but simulation performance related, is that I'm unsure I'm making good use of the Py5Shape object .set_strokes() & .set_fills methods. I should open a discussion about it with my code when I get the chance... |
Beta Was this translation helpful? Give feedback.
-
I personally like the idea of the "update" name, it seems to be a pretty common pattern that when you write a small simulation, for example several bouncing balls, to end up with something like:
So it would seem pretty natural to me to do something like that:
But I don't know if the performance boost from using the update function would make up for the performance hit of iterating two time on the list. I'm more wondering about the case where the simulation is time dependent and you use a deltatime in your update, would it lead to weird cases ?
But then you decide to implement your simulation with the new update function, would you end up with something like this ?
That would probably not be noticeable, but might be weird to understand what is happening. I am missing something ? |
Beta Was this translation helpful? Give feedback.
-
This discussion thread is to introduce a new py5 feature: a user
update()
function that is called before every call todraw()
. I'll explain how it works and why it is useful. I'd like to hear others' thoughts on this feature and how to best explain it and introduce it to others.Bottom line, this new feature can make small (5-10%) performance improvements in many cases. It is not a game changer, but it is a simple way to make a small improvement and will benefit someone who is attempting to performance tune a Sketch.
To begin, consider the following py5 sketch. This example draws to an oversized Py5Graphics object and then draws the Py5Graphics object to the screen. This example a bit contrived to exagerate an performance issue but for now it is useful to clearly demonstrate the performance benefit of the new
update()
function.On my old MacOS laptop, this Sketch gets about 2.5 frames per second. The giant Py5Graphics object hurts performance. Also, the 150 ms pause in
slow_function()
doesn't help.Now, let's think about the
draw()
function. Conceptually, we think aboutdraw()
being called repeatedly, which no gap between the end of one call and the beginning of the next. However, this isn't the truth. There is a small time gap between the end of one call todraw()
and the beginning of the next.We can measure this gap with some extra code to grab some timestamps:
If I run that code for a while, I can then analyze the results:
]
Here are the results:
These numbers are telling us that when this Sketch is running, 60% of the time is spent in the
draw()
function, and 40% of the time is spent in the time gap between the end of one call todraw()
and the beginning of the next.I do want to make it clear that these numbers are not typical. For a more typical Sketch, 85-90% of the time is spent in
draw()
and 10-15% of the time is spent in the time gap between the end of one call todraw()
and the beginning of the next call todraw()
. This example is contrived to exagerate the time gap. I happen to know that Processing does a lot of work on our behalf to prepare the large Py5Graphics object to be used as a texture, and that work has a cost. This work is done after thedraw()
function completes. Processing always does some work for us after thedraw()
function completes, but in this case the work is more expensive than usual.Now here's the key point: because of the Python + Java design of py5, during that gap, the Python interpreter is idle. The purpose of the new
update()
function is to give the user an opportunity run code during the time between calls todraw()
that the Python interpreter would otherwise be idle.Let's ignore the contrived nature of this Sketch and think about how we can use the new
update()
function to improve performance. Theupdate()
function is guaranteed to complete before each call todraw()
. You can't draw anything to the screen in thisupdate()
function, similar to the limitations of the mouse and key event functions such asmouse_pressed()
andkey_pressed()
. However, you can do other things, such as prepare data for the next call todraw()
. For our example, let's moveslow_function()
to theupdate()
function.How did the measurements change?
Now the Sketch has a frame rate of 3.57 fps, which is a ~41% improvement over the version without
update()
.This 41% performance improvement is not typical. The reason why it helped so much is because for this Sketch the idle time between calls to
draw()
was so large. That excessive idle time left a lot of room for improvement. Normally the idle time would be much smaller, perhaps around 10-15%. For those Sketches, the frame rate could improve by maybe 5-10%.Is this new feature something to get excited about? No. It isn't going to magically turn a slow Sketch into a fast Sketch. And for many use cases, a 5-10% improvement isn't worth the bother. However, someone who is performance tuning a Sketch will typically make a lot of small improvements that add up to a big improvement. This new
update()
function is a quick way to provide one of those small improvements.Is this a feature you'd want to teach to beginner coders? No. I recall @villares has talked about the "cognitive load" of beginners and adding a new function to the mix only complicates things for learners. I agree with that. Not everyone cares about a 5-10% performance improvement, and that's fine.
Note the
update()
function could be added to Processing or perhaps even p5. I did notice there is a request for new feature proposals for p5 2.0. I don't think this would add as much value to p5 or Processing because neither has the dual-language design of py5. In py5, Python interpreter just doesn't compete with the Java Virtual Machine for execution resources. This contrasts with a p5 Sketch, where the user code and the p5 library run along side each other in the browser. However, I could be wrong, and it could help. It would be interesting to measure the idle time in a p5 Sketch and see if there is a similar opportunity for improvement. If someone would like to work with me on that, let me know.Beta Was this translation helpful? Give feedback.
All reactions