X Tutup
Skip to content

ClassDB: Use AHashMap for property_setget and constant/signal_map#112129

Merged
Repiteo merged 1 commit intogodotengine:masterfrom
DeeJayLSP:asetget
Oct 29, 2025
Merged

ClassDB: Use AHashMap for property_setget and constant/signal_map#112129
Repiteo merged 1 commit intogodotengine:masterfrom
DeeJayLSP:asetget

Conversation

@DeeJayLSP
Copy link
Contributor

@DeeJayLSP DeeJayLSP commented Oct 28, 2025

(During testing I found this is part of #101340, but this is a simple and harmless change that wouldn't require a whole rewrite and has a very low chance of regressions, so I opened it anyway)

Note: Might conflict with #106646, which also touches the same HashMaps. As long as the proposed property_cache is also an AHashMap, it's possible to gain around 0.9% more FPS. If anything, that one has priority over this.


ClassDB::get_property() is one of the biggest bottlenecks in GDScript (actually, in Variant itself) as seen when profiling.

I did a bit of experimenting by making property_setget, constant_map and signal_map AHashMap instead of HashMap. Tests were run on a modified version of Gaijin's BunnyMark (stress test of many GDScript instances) in a release production build, 3 times, with the average FPS of 20 seconds written down:

500 bunnies:

Build Lowest Highest
master 2157 2175
PR 2320 2337

1000 bunnies:

Build Lowest Highest
master 1445 1446
PR 1567 1582

5000 bunnies:

Build Lowest Highest
master 311 312
PR 340 349

Overall, FPS was increased between a minimum of 2.8%.

During profiling on a template_debug build with debug symbols, ClassDB::get_property() almost doubled in cycles, but it was mostly caused by MethodBindTRC::call(), which I believe means a bottleneck removed rather than a bottleneck added.

Build sizes did not change.

@DeeJayLSP DeeJayLSP requested a review from a team as a code owner October 28, 2025 17:16
@clayjohn
Copy link
Member

During profiling on a template_debug build with debug symbols, ClassDB::get_property() almost doubled in cycles, but it was mostly caused by MethodBindTRC::call(), which I believe means a bottleneck removed rather than a bottleneck added.

That makes sense. Profiling captures a stream over time. So if you have more FPS, then a given function will be called more times and will consume more cycles.

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good to me

@clayjohn clayjohn added this to the 4.6 milestone Oct 28, 2025
@DeeJayLSP DeeJayLSP changed the title ClassDB: Use AHashMap for property_setget ClassDB: Use AHashMap for property_setget and constant/signal_map Oct 28, 2025
@DeeJayLSP
Copy link
Contributor Author

DeeJayLSP commented Oct 28, 2025

Further experimenting showed that modifying constant_map and signal_map improved things even more.

I tried to apply to method_map too, but that actually slowed things down.

Benchmarks updated to the new changes.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good to me.

@clayjohn clayjohn self-requested a review October 28, 2025 23:02
@Repiteo Repiteo merged commit a0cde1e into godotengine:master Oct 29, 2025
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Oct 29, 2025

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

X Tutup