The work I’m doing requires a mostly static 3d world, with changes happening solely at the request of the user. I have wrapped Panda inside a wx window, using code similar to [url]integrating a wxPython GUI into a Panda app].
The CPU should not be burning out an entire core just rendering the scene at 60fps or whatever.
It does not help. I believe this is because Panda does not own the main loop, since wx does. Wx’s main loop is as follows. Note that it is perfectly capable of maxing out a core since it is in effect an infinite loop.
def wx_loop(self, task):
sleep(0) # to be discussed soon
If I can’t get Panda to chill, the next logical step is to convince wxPython to give the rat race a break. Searching on Google for “wxpython yield timeslice” brought me to this Allegro thread that described a function in their framework that yields the remainder of its timeslice to the next process. The thread implied that using that function would decrease CPU usage. Unfortunately, there does not seem to be an implementation of yield-timeslice() in Python, Panda3D, and wxPython.
Following up on the yield-timeslice() idea, I looked for a way to yield a thread in Python. I found a discussion about “Threading unfairness” that states:
But in the code you’re posting, it appears that Panda does indeed own the main loop. The wx loop you post is a Panda task. When it finishes, it returns task.cont, which allows Panda to service the rest of its tasks and then cycle the main loop.
In any case, putting a task that calls time.sleep(0.01) or any nonzero value should certainly stop the CPU from running away. If it doesn’t, something is very wrong.
Exactly. It “works”, but only by slowing down the entire program. What I’d like is the equivalent of what wxPython does by default. When you run the basic hello world example (see below), the CPU doesn’t even twitch. I’d like Panda to do the same, even if it means disabling the entire Panda event queue and only redrawing when I want.
Does it actually slow down the program, so that you can perceive that it is running slower, or do you just know that it’s slowing down the program so you don’t want to do it? Because a sleep of 1/100th of a second per frame should not have any perceptible effect on program responsiveness.
There is a difference in philosophy between 2-d toolkits like wx, and 3-d toolkits like Panda. In the former, applications are almost entirely event-driven, and typically spend large amounts of time doing nothing while waiting for user input. In the latter, applications are usually rich and heavily animated, and user input is used to guide the experience, not control it. Furthermore, the 3-d hardware won’t refresh the buffer contents to the window automatically, so if the window is covered and then uncovered, an immediate redraw is necessary. Also, a 3-d window is usually the user’s primary interface while it is running.
So Panda, in keeping with this typical philosophy of 3-d engines, focuses more on rendering every frame, than on rendering only when something changes.
If you only want to render the scene when something changes, then you can remove the igloop task and call base.graphicsEngine.renderFrame() only when you know the window needs redrawing. There are a few subtleties with this, though–you may want to move the clock ticking into the task manager, for instance, and a few other things that I’d have to think about a little longer.
But at the end of the day, are you really sure you need to go through all this trouble? If your goal is reducing CPU utilization without impacting responsiveness, a sleep should be sufficient, and if it isn’t I’d like to know more about it. But if your goal is bending Panda to follow the typical 2-d event philosophy for some more abstract reason, then you do need to do all this.
I’m finding that up to 0.005 secs of sleep is unnoticeable, and drops my CPU from 48% to 28%. Any more sleep than that and strafing etc is a little jittery, and the wx menubar is slower to respond.
This issue seems like a limitation of Panda’s implementation rather than a philosophy. As you mentioned, it would be manageable to fix Panda or work around it, but my code is just a prototype so I’ll live with the CPU load. Thanks for your tip on where to start, though. If I end up trying to solve it that way, I’ll post again with any news.