godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.51k stars 21.07k forks source link

Instancing some objects takes a lot of more time in Godot 4 than in Godot 3.x #48978

Open qarmin opened 3 years ago

qarmin commented 3 years ago

Godot version: 3.4.beta.custom_build. ea0ccf638 4.0.dev.custom_build. 846b3855b

OS/device including version: Ubuntu 21.04 Nvidia 970 465 drivers

Issue description: When I instanced 1000 objects(without adding them to tree), then I saw that instancing some of classes takes even 200 times more time in Godot 4.0 than in Godot 3.x. 40 the slowest classes in Godot 3.x (1000 runs)

World:                                   2555 miliseconds
FileDialog:                              2450 miliseconds
ColorPicker:                             1381 miliseconds
GraphEdit:                               516 miliseconds
World2D:                                 358 miliseconds
Tree:                                    331 miliseconds
TextEdit:                                314 miliseconds
ConfirmationDialog:                      187 miliseconds
SpinBox:                                 161 miliseconds
Viewport:                                158 miliseconds
LineEdit:                                104 miliseconds
AcceptDialog:                            102 miliseconds
ScrollContainer:                         73 miliseconds
Animation:                               67 miliseconds
AudioEffectEQ21:                         62 miliseconds
MainLoop:                                60 miliseconds
Sprite3D:                                58 miliseconds
MarginContainer:                         57 miliseconds
OptionButton:                            54 miliseconds
CPUParticles2D:                          46 miliseconds
OpenSimplexNoise:                        46 miliseconds
AnimatedSprite3D:                        46 miliseconds
MenuButton:                              45 miliseconds
RichTextLabel:                           42 miliseconds
HTTPRequest:                             40 miliseconds
AnimationNodeBlendSpace2D:               40 miliseconds
AnimationNodeBlendSpace1D:               38 miliseconds
AudioEffectEQ10:                         34 miliseconds
WebSocketClient:                         33 miliseconds
Particles:                               32 miliseconds
AnimationNodeTransition:                 31 miliseconds
WebRTCPeerConnection:                    29 miliseconds
WindowDialog:                            27 miliseconds
ItemList:                                27 miliseconds
SpatialMaterial:                         26 miliseconds
Particles2D:                             26 miliseconds
AudioEffectEQ6:                          25 miliseconds
PopupMenu:                               23 miliseconds

40 the slowest classes in Godot 4.0 (1000 runs)

FileDialog:                              72016 miliseconds
ProceduralSkyMaterial:                   50616 miliseconds
PhysicalSkyMaterial:                     44504 miliseconds
Tree:                                    32179 miliseconds
ColorPicker:                             27501 miliseconds
PanoramaSkyMaterial:                     25970 miliseconds
SpinBox:                                 22630 miliseconds
TextEdit:                                19804 miliseconds
GraphEdit:                               15373 miliseconds
LineEdit:                                14857 miliseconds
World3D:                                 6080 miliseconds
PopupMenu:                               5840 miliseconds
ProgressBar:                             5829 miliseconds
SubViewport:                             5163 miliseconds
PopupPanel:                              4999 miliseconds
Window:                                  4803 miliseconds
OptionButton:                            4582 miliseconds
MenuButton:                              4417 miliseconds
PhysicsMaterial:                         4206 miliseconds
CodeEdit:                                4038 miliseconds
Object:                                  3838 miliseconds
Popup:                                   3799 miliseconds
ConfirmationDialog:                      2048 miliseconds
CPUParticles2D:                          689 miliseconds
AcceptDialog:                            375 miliseconds
World2D:                                 295 miliseconds
ScrollContainer:                         158 miliseconds
RichTextLabel:                           153 miliseconds
AnimatedTexture:                         143 miliseconds
WorldEnvironment:                        116 miliseconds
Animation:                               114 miliseconds
AudioEffectEQ21:                         59 miliseconds
VisualShader:                            55 miliseconds
StandardMaterial3D:                      53 miliseconds
HTTPRequest:                             51 miliseconds
OpenSimplexNoise:                        46 miliseconds
ItemList:                                41 miliseconds
AnimationNodeBlendSpace2D:               39 miliseconds
CheckBox:                                38 miliseconds
AnimationNodeBlendSpace1D:               36 miliseconds

Minimal reproduction project: Projects are almost same, but differs in using of Callable and String -> int conversion

Godot 4.0 - SlowClasses4.zip Godot 3.x - SlowClasses3.zip

Calinou commented 3 years ago

The slow LineEdit/TextEdit instantiation is due to the context menus being created for every node, rather than using a single context menu shared across all nodes (only one may appear at a given time).

The new context menus feature a lot more things for TextServer/RTL support and the like, so they are slower to create. This also affects nodes that contain LineEdits such as ColorPicker.

YuriSizov commented 3 years ago

I’d like to point out that each individual popup menu is still slower, i.e. the new context menu options wouldn’t cause such massive slowdowns in 3.x. It’s just that every node is 3-4 times slower, and complex nodes, like ColorPicker, are slower still because they rely on several nodes themselves.

Also, @qarmin, I’m pretty sure these are microseconds, not milliseconds.

qarmin commented 3 years ago

This are milliseconds. I instanced each object 1000 times(updated post).

reduz commented 3 years ago

@qarmin Can you also test on master with --single-window command line? I would like to know how much is this the fault of the underlying window manager.

qarmin commented 3 years ago

I don't see any real difference (max ~5%, but this is probably caused by OS load). Since I'm using Nvidia on Linux, I think that users which use different OS or graphics card can have better results because looks that this combination with Godot Vulkan doesn't work fine.

Not sure if this will be helpful, but I done check with only 100 runs and I got this hotspot flame graphs Godot3 perf3 Godot4 perf4

reduz commented 3 years ago

@qarmin Yeah shader compilation takes a lot of the startup time, but it should be only startup time. This week I am going to work on shader caching, which should reduce startup time massively.

reduz commented 3 years ago

There were many optimizations merged recently. Do you think you could give a try to this benchmark again on the same hardware?

qarmin commented 3 years ago

Now it looks a better in master branch but still creating e.g. Sprite3D is ~60x slower than in 3.x branch

Ubuntu 21.04 Nvidia 970 465 drivers

4.0.dev.custom_build. bb037de95 3.4.beta.custom_build 51f824787

Projects Godot4 - SlowClasses4.zip Godot3 - SlowClasses3.zip

Tests with 1000 runs

Godot3

World:                                   3704 miliseconds
FileDialog:                              2367 miliseconds
ColorPicker:                             1333 miliseconds
World2D:                                 554 miliseconds
GraphEdit:                               534 miliseconds
Tree:                                    324 miliseconds
TextEdit:                                309 miliseconds
ConfirmationDialog:                      180 miliseconds
SpinBox:                                 161 miliseconds
Viewport:                                156 miliseconds
AcceptDialog:                            100 miliseconds
LineEdit:                                99 miliseconds
ScrollContainer:                         71 miliseconds
Animation:                               66 miliseconds
Sprite3D:                                60 miliseconds
AudioEffectEQ21:                         60 miliseconds
Listener:                                57 miliseconds
OptionButton:                            53 miliseconds
AnimatedSprite3D:                        49 miliseconds
CPUParticles2D:                          48 miliseconds
MenuButton:                              47 miliseconds
OpenSimplexNoise:                        45 miliseconds
RichTextLabel:                           42 miliseconds
AnimationNodeBlendSpace2D:               39 miliseconds
AnimationNodeBlendSpace1D:               37 miliseconds
Particles:                               35 miliseconds
HTTPRequest:                             34 miliseconds
WebSocketClient:                         32 miliseconds
AudioEffectEQ10:                         32 miliseconds
InputMap:                                30 miliseconds
AnimationNodeTransition:                 29 miliseconds

Godot4

PhysicalSkyMaterial:                     10477 miliseconds
ProceduralSkyMaterial:                   9416 miliseconds
FileDialog:                              8888 miliseconds
Sprite3D:                                3845 miliseconds
PanoramaSkyMaterial:                     3234 miliseconds
Tree:                                    3055 miliseconds
World3D:                                 1753 miliseconds
ColorPicker:                             1741 miliseconds
Window:                                  1376 miliseconds
PopupMenu:                               1255 miliseconds
SubViewport:                             1200 miliseconds
OptionButton:                            1169 miliseconds
PopupPanel:                              1166 miliseconds
MenuButton:                              1110 miliseconds
Popup:                                   1026 miliseconds
ConfirmationDialog:                      658 miliseconds
CPUParticles2D:                          647 miliseconds
GraphEdit:                               405 miliseconds
PhysicsMaterial:                         378 miliseconds
AcceptDialog:                            361 miliseconds
CodeEdit:                                344 miliseconds
AnimatedSprite3D:                        278 miliseconds
TextEdit:                                170 miliseconds
AnimatedTexture:                         149 miliseconds
Animation:                               99 miliseconds
WorldEnvironment:                        96 miliseconds
World2D:                                 87 miliseconds
SpinBox:                                 84 miliseconds
AudioEffectEQ21:                         63 miliseconds
RichTextLabel:                           52 miliseconds
ScrollContainer:                         50 miliseconds
akien-mga commented 3 years ago

How are things faring now on an optimized build?

Calinou commented 2 years ago

I noticed that unlike in 3.x, Viewport now defaults to a shadow atlas size of 2048 in master. While this allows for point light shadows to be displayed out of the box in user-added viewports, this makes them slower to instantiate and consume more memory even if no lights with shadows are present in the viewport.

https://github.com/godotengine/godot/blob/bf0253bab936f053bb5ae56e6fcf67defaf9afbc/scene/main/viewport.h#L288

While this would resolve https://github.com/godotengine/godot/issues/23732, I'd suggest setting it back to 0 by default to avoid this performance regression.