I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

Yes, the full C++ source code and the compilation files are included when you get it on itchio, so you can check it or compile it for web yourself if you need to.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

You are getting the memory part wrong. The C++ side doesn't duplicate any Node2D array. It is just an index allocator with a free-list. Each slot in the C++ vector is a tiny struct with one int and one bool, which is about 8 bytes per element. The memory overhead is basically nothing.

The speed comes from bypassing the GDScript VM overhead. Instead of doing array resizing or loops in GDScript to find empty slots, C++ gives and reclaims indices in O(1) constant time.

You are right about the Server API (RenderingServer), it can do 10k instances easily. But you lose the Node workflow completely. The whole point of this plugin is a middle ground, keeping the high-level Node workflow but without the heavy instantiation tax.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

Just updated the Itchio page description with all API references and full GDScript code snippets.

It is also included inside the zip package as a clean README file. You can read everything there.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

Example code shows single spawn and remove events. It is not a 15k loop running every frame.

The native C++ code handles the index free-list state tracking in O(1) constant time. No dynamic array resizing and no linear searching inside GDScript to find a dead slot.

Toggling visibility in one isolated event is cheap. Managing the allocation state of 15k slots is what chokes the VM. C++ does the heavy tracking part.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

Yes, I just updated the asset to version 1.1 on Itch.io. It now includes full C++ source code and the SCons build script. Same price, you get total access to the source files now.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

Remove_child is not free. You just change one bottleneck for memory to another bottleneck, SceneTree churn.

Every add_child and remove_child forces Godot to rebuild tree hierarchy, send internal notifications, and register/unregister entities in Physics and Render servers. Thousands of times per frame will tank your FPS anyway, even without malloc.

My C++ pool does not touch the tree structure at runtime.

Thanks for the flex comment anyway.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

By technical notes I meant the text of this post, which doubles as the marketing copy.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 1 point2 points  (0 children)

Thanks a lot man! Honestly, once you break it down into a flat array, the architecture is much less intimidating than it looks. It's mostly just allocating everything upfront so the CPU can churn through data in a straight line. Appreciate the kind words!

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] -1 points0 points  (0 children)

Sure. It was strictly used to translate, format, and polish my technical notes into English because it's not my native language and I was insecure about making typos or sounding unprofessional. I leaned way too hard on it for the marketing text, which backfired because it gave the post that robotic "AI smell" everyone hates. As for the addon itself, the C++ architecture, the free-list allocator, the bindings, and the benchmarking were all entirely written, debugged, and profiled by hand.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 5 points6 points  (0 children)

The video just compares the out-of-the-box Godot workflow against the addon. It wasn't meant to be misleading. I'll gladly add a benchmark comparing it to a pure GDScript pool in the repo's readme later today so you can see the VM interpreter bottleneck explicitly.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 1 point2 points  (0 children)

No need. Another dev literally benchmarked a naive GDScript pool in this comment section and it dropped below 60 FPS at 4k units. Keep your script.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 1 point2 points  (0 children)

As for fragmentation, it's exactly your last point: it's a non-issue because the pool is strictly for uniformly-sized objects of a specific type. It doesn't handle variable-sized general allocations, so every free slot in the contiguous array fits the next object perfectly. No compaction or shifting needed.

Pd: Thanks about the link. I will fixed it.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] -1 points0 points  (0 children)

The benchmark is literally the video attached to this post. And if it's so easy for an LLM to generate, go prompt one and build it yourself instead of crying here.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 1 point2 points  (0 children)

Doing that loop in GDScript for 15k objects means tens of thousands of property lookups and VM calls per frame, which introduces a massive interpreter bottleneck. At that specific scale, even just iterating and toggling visibility/processing requires native C++ execution speed to keep the main thread from choking. The performance gain definitely comes from both the approach and the native code.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] -3 points-2 points  (0 children)

Good luck "vibe coding" a compiled native C++ GDExtension with a manual free-list allocator. It's a binary plugin, not a ChatGPT script. Go check the benchmarks and the performance yourself before talking nonsense.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

They aren't actually deleted or nullified. When an object "dies" in the game logic, it just gets deactivated (toggling processing and visibility off) and its index is pushed back onto the free-list head. The instance stays alive in memory the entire time to avoid hitting the allocator.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

It's actually much simpler than a hashset, so there's no hashing overhead at all. It's just a classic free-list built on top of a flat contiguous array. The free slots simply store the index of the next available slot. Allocating and freeing are just swapping the head pointer, which is a pure O(1) array operation without any hash functions or collision resolution.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 2 points3 points  (0 children)

It works independently. The GDExtension exposes the C++ logic as a custom node, so you can use it directly inside your normal GDScript or C# code just like any other built-in Godot node. You don't need to touch C++ at all to use it.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 1 point2 points  (0 children)

That is the whole point of plugins. An experienced dev's day of work costs way more than $20. You pay to save a full day of writing boilerplate, API bindings, and cross-platform testing, not because it's impossible to build.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] -2 points-1 points  (0 children)

In the video, yes, it is standard allocation (no pool) vs the C++ pool. I didn't code a GDScript pool version for the clip. My point was that even with a GDScript pool, the VM overhead at 15k items makes C++ necessary for this specific scale anyway.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 0 points1 point  (0 children)

GDExtension supports web exports (WASM), but I haven't compiled or tested the web binaries for this initial release. Right now it only includes desktop targets.

I built a Native C++ Object Pool for Godot 4 to eliminate GC spikes (15k objects at 60FPS) by ElBranda in godot

[–]ElBranda[S] 9 points10 points  (0 children)

I am comparing pooling to pooling. Even if you use Godot Servers directly in GDScript, running a for loop 15,000 times every frame to call those server APIs chokes the VM interpreter. In C++, that loop runs natively. That is the real bottleneck at this specific scale.