Open TheOrioli opened 7 months ago
I am using Godot4.2 C#. I found FPS jitter rapidly, especially run code in Android(ualcomm - Adreno (TM) 630). What's strange is that in my scene, there are only around 10 nodes, and I've added a cache pool to avoid frequent node creation, but there is still an issue with FPS jitter. When I checked the jitter frames, I found that the Physics Frame went from less than 1ms to over 100ms.
@sky94520 What you're reporting is likely an unrelated issue, as it encompasses an entire project and not a minimal reproduction case like OP did.
I decided to remove the call to set the Text value, just to remove doubts that the problem lies in marshaling between C# calls to the Label property.
This is a graph of only 1 node being active, GDScript vs C#, and we can see there is basically no difference between the two, which makes sense
However, increasing the number of nodes to just 10 creates a 14% difference GDScript C#
And, finally increasing to 100 nodes creates an almost 50% difference in favor of GDScript GDScript C#
Here is the updated project zip, but the basic difference is that the script truly does nothing except some basic math test_mono_method_cache.zip
Tested versions
System information
Godot v4.3.dev4.mono - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2070 SUPER (NVIDIA; 31.0.15.4633) - AMD Ryzen 9 3900X 12-Core Processor (24 Threads)
Issue description
Short Version
C# performance seems to have suffer due to StringName equality checks in generated methods like
HasGodotClassMethod
andInvokeGodotClassMethod
Long Version
I noticed that performance in my game drops sharply with a large number of nodes doing basically nothing. So I created a small repro project to try and explain what I have observed.
In the repro project we have a very simple script that toggles a Label from
a
tob
every second. This is done in a_process
callback in both GDScript and C#. We instantiate 1000 instances of the label to simulate a large number of nodes. At a too large number (10000) the project is very slow, so differences between GDScript and C# are not noticable.( all screenshots are in the repro project) Here are the graphs for the 4.x version of Godot: GDScript C#
All 4.x versions tested exhibit the same behavior, which is GDScript being almost double the speed of C#.
For comparison here are the graphs for 3.5.3, where C# is faster than GDScript: GDScript C#
I ran a dotTrace using Rider to try and figure out what is going on, and here are the results for 4.2.1
it's here I first noticed the equality checks on StringNames taking up a bit of time. Which led me to assume that the if-else chain in the
HasGodotClassMethod
andInvokeGodotClassMethod
might be part of the problem.I experimented in modifying the ScriptGenerators to use cached method calls instead of comparison checks https://github.com/TheOrioli/godot/commit/c291f64568899bb17d300655aa6a57179ae91cb0 and it seems to provide a bit of a speedup in my main project, but I do not know how to change those methods for built-in godot types.
You can see a small pyramid in the flame graph disappear under
TestLabel.InvokeGodotClassMethod
I there is definitely something here, and there is potential to eliminate all those comparison checks which should provide a speedup and bring C# closer to GDScript in performance. I am hoping someone more familiar with the codebase can help out in figuring this out and testing more properly.
This behavior unfortunately means that making lots of small scripts in C# will lead to unintended performance degradation in games.
Steps to reproduce
main.tscn
with the Node property "Use CSharp" set to falsemain.tscn
with the Node property "Use CSharp" set to trueMinimal reproduction project (MRP)
4.3-dev4, contains screenshots from above in folder test_mono_method_cache.zip 3.5.3 test_mono_method_gd3.zip