godotengine / godot-docs

Godot Engine official documentation
https://docs.godotengine.org
Other
3.6k stars 2.97k forks source link

Getting data from the servers - clarify or further explain what kind of knowledge needed #6117

Open vgnod opened 1 year ago

vgnod commented 1 year ago

Your Godot version: 3.5, "latest"

Issue description: In "Optimization using Servers:

Try to never request any information from RenderingServer, PhysicsServer or Physics2DServer by calling functions unless you know what you are doing.

What kind of knowledge is needed? Is it possible to make instructions containing said knowledge? If not, where one can educate himself? What system or peace of code should one explore to gain that knowledge?

This will severely decrease performance if you call them every frame (and it won't be obvious why).

Built - in functions often get data from servers each frame and multiple times a frame. What's the difference between build in function's calls to servers and user code calls? If there is some sort of system for proper arrangement of this calls, can it be accessed? If not, why? If there is no such system, can preferred call patterns be found in code, by exploring built in functions? Is it good idea to use their call patterns as reference?

URL to the documentation page (if already existing): https://docs.godotengine.org/en/latest/tutorials/performance/using_servers.html https://docs.godotengine.org/en/3.5/tutorials/performance/using_servers.html

Calinou commented 1 year ago

See https://github.com/godotengine/godot/issues/60625 for an example of this situation.

cc @lawnjelly

lawnjelly commented 1 year ago

No expert at this here, and as for the core source code, there are plenty of examples of bad "gets" from the servers which should not have been implemented in the way they are. I'm loathe to write documentation, having only a little reverse engineered knowledge from the system.

As I understand it, the servers are written to be potentially run on a different thread than the scene tree, and communication between the client (scene tree etc) and servers takes place via a command queue. That is you push commands to the queue, and they are executed in order, but not necessarily at the same time you posted them to the queue.

This is the typical model for graphics APIs such as OpenGL. You feed the pipeline, and it gets done at a later time when makes sense for the server.

This works great for code that just pushes commands to the command queue. The problem comes when you have want to read some info back from the server. If you try and read something back, you can then potentially create a stall whereby it has run all the pending commands in the queue to catch up to the point where you read some data. This can potentially be very expensive, or cause a hitch / dropped frame etc.

So in general the data flow should be one way from the client to the server. Wherever possible reading back should be designed out of the API. If it has to be done it should be extremely carefully and should not be used in regular use except via mechanisms specifically for this purpose, such as sync points (e.g. physics), or deferred callbacks (where the data to be sent to the client is posted back by a deferred thread safe queue, see e.g. VisualServerCallbacks in 3.x). The exception tends to be for things like loading level data, where the stall is just expected (glitches during loading a level are not necessarily a problem, unless say streaming).

Another alternative is to keep a copy of state client side, or duplicate processing client side, precisely to prevent stalls. The physics interpolation does this for instance in the get_global_transform_interpolated() command, which would otherwise cause a stall.

vgnod commented 1 year ago

Thank you for the reply. Well yes, something less vague than current description must be made by developers who work with the servers, and probably that will not happen any time soon. However, i think at least physics server's sync should be explained. It's basically

PhysicsServer3D::get_singleton()->sync();
PhysicsServer3D::get_singleton()->flush_queries();

if (OS::get_singleton()->get_main_loop()->physics_process(physics_step * time_scale)) {
            exit = true;
            break;
}
PhysicsServer3D::get_singleton()->end_sync();

Is there any caveats? If no, it can be mention in the docs that during _phycics_process it is safe to call the server. There is space and body direct states and technically they are part of the server i guess, and we use it freely.