How do I call a function more than 1,000 times every second without interrupting _process routine nor changing FPS?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By kylxbn

Hello! I would like to apologize ahead if my question was hard to understand.

I am making a virtual machine emulator in Godot. It’s a custom machine, my own CPU implementation, GPU, et cetera.

The important thing to understand is that currently, the _process routine and the _physics_process are the important parts. The _process routine takes the current picture from the emulated GPU and displays it as a texture. The _physics_process calls the CPU once so that it can process instructions.

The _process routine is called 60 times every second (if possible) so the screen is updated 60 times per second, and that’s perfectly fine. But since _physics_process is called 60 times per second by default, this makes the CPU run at 60 Hz, and even the first Nintendo ran at 1,790,000 Hz (1.7 MHz). To help improve this, I have set the physics FPS setting to 480 Hz, and that did improve the speed of the emulated CPU a lot. But I can’t help but doubt that this is the right way to approach this problem.

Since 480 Hz is still quite slow for a CPU, I would like to increase this to at least 1,024 or 2,048 Hz. I’m sure I can just try setting the physics FPS to that, but I would like to ask first if I am approaching this correctly, or if there are better ways to handle this situation.

The code is open-source, and the code responsible for calling the CPU and updating the screen can be seen here.

I kindly ask for the community’s guidance regarding this. Thank you very much in advance!

:bust_in_silhouette: Reply From: Calinou

Increasing Physics Fps above 1,000 will slow down physics simulation, so you don’t want to do that. (This is no longer allowed in Godot 3.3.3 and later because of this issue.)

Instead, I would look at performing multiple simulations per physics step somehow (perhaps using threads?).

Thank you very much for the heads up! So I wasn’t wrong with my gut feeling that I shouldn’t be messing around with the physics FPS.

I was able to find a workaround which enabled me to reach 1,875 Hz (1.9 KHz) CPU speed by

  • reverting physics FPS back to 60 (since I won’t use it for non-physics reasons again)
  • adding a Timer node that calls a function every 0.016 second (or 62.5 times per second)
  • the function called by the Timer calls the CPU 35 times per call

The CPU is effectively called 1,875 times per second (in bursts, and not evenly in time, but I don’t think I need to be more accurate than that)

Some benchmarking shows that I still have around 16,000 microseconds left until the next Timer tick, so yeah, it’s working fine, I guess! More opportunities for more features, as I plan to implement more features such as sound output, keyboard polling, virtual hard disk access… et cetera, so this is very hopeful.

Thank you very much for your help! I really appreciate it!

kylxbn | 2021-09-11 04:49

:bust_in_silhouette: Reply From: sash-rc

If you don’t use physics, then you don’t need _physics_process at all.

To make some procedure completely independent you need a separate thread.
The hard part is that you will need synchronization, and it will be hard to achieve very precise “CPU” timing, even with “high resolution” timers (although 1000 times/sec is probably doable).

Thank you very much for the heads up! I was indeed not using _physics_process so I removed it.

I was able to find a workaround which enabled me to reach 1,875 Hz (1.9 KHz) CPU speed by

  • reverting physics FPS back to 60 (since I won’t use it for non-physics reasons again)
  • adding a Timer node that calls a function every 0.016 second (or 62.5 times per second)
  • the function called by the Timer calls the CPU 35 times per call

The CPU is effectively called 1,875 times per second (in bursts, and not evenly in time, but I don’t think I need to be more accurate than that)

Some benchmarking shows that I still have around 16,000 microseconds left until the next Timer tick, so yeah, it’s working fine, I guess! More opportunities for more features, as I plan to implement more features such as sound output, keyboard polling, virtual hard disk access… et cetera, so this is very hopeful.

Thank you very much for your help! I really appreciate it!

kylxbn | 2021-09-11 04:51