You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In C#, StringNames and NodePaths can be a footgun for garbage collection issues which cause performance spikes.
This can be a very insidious issue because of implicit casting:
Input.IsActionPressed("action");// Created a StringName.
GetNode("path/to/node");// Created a NodePath.
To test the extent of the issue, I wrote the following code:
using Godot;using ZiggyCreatures.Caching.Fusion;publicpartialclassStringNameSpammer:Node{publicintTest=10;publicboolUseCache=true;privatereadonlyFusionCacheCache=new(new FusionCacheOptions());publicoverridevoid_PhysicsProcess(doubleDelta){for(intCounter=0;Counter<10_000;Counter++){if(UseCache){
Get(Cache.GetOrSet("Test",_ =>(StringName)"Test"));}else{
Get("Test");}}}}
It creates, uses and discards 10,000 StringNames per physics frame, to be garbage collected. This uses FusionCache, but any capped-size dictionary could be used.
When UseCache is false, I get consistent 30ms spikes:
When UseCache is true, I get a steady 17ms:
Ideally, the C# API would exclusively use strings rather than StringNames. But until this is implemented, there should be a better StringName/NodePath API.
In my code, I've been doing this:
using ZiggyCreatures.Caching.Fusion;publicstaticclassRecycleExtensions{privatestaticreadonlyFusionCacheStringNameCache=new(new FusionCacheOptions());privatestaticreadonlyFusionCacheNodePathCache=new(new FusionCacheOptions());/// <summary>/// Convert the string to a StringName, recycling if possible./// </summary>publicstatic StringName ToStringName(thisstringString){return StringNameCache.GetOrSet(String,_ =>(StringName)String)!;}/// <summary>/// Convert the string to a NodePath, recycling if possible./// </summary>publicstatic NodePath ToNodePath(thisstringString){return NodePathCache.GetOrSet(String,_ =>(NodePath)String)!;}}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
In C#, StringNames and NodePaths can be a footgun for garbage collection issues which cause performance spikes.
This can be a very insidious issue because of implicit casting:
To test the extent of the issue, I wrote the following code:
It creates, uses and discards 10,000 StringNames per physics frame, to be garbage collected. This uses FusionCache, but any capped-size dictionary could be used.
When
UseCache
is false, I get consistent 30ms spikes:When
UseCache
is true, I get a steady 17ms:Ideally, the C# API would exclusively use strings rather than StringNames. But until this is implemented, there should be a better StringName/NodePath API.
In my code, I've been doing this:
Then I can do:
However, I think this would be better implemented in the API itself, because of reduced footguns and simpler syntax.
Here's the StringName cast according to the reflector:
This could be changed to this:
Here's the project I used for profiling: stringnamestest.zip
Beta Was this translation helpful? Give feedback.
All reactions