Home Artists Posts Import Register

Content

I have been spending the past few days making some large changes to try to speed up some operations which cause the interface to freeze or lag. This happens whenever Blockhead has to instance a lot of Godot scenes at the same time, for example if you create 100 blocks, drag a selection box around them all and press CTRL+C to create 100 more blocks, the interface will currently freeze for a moment while all the new blocks are created.

Another thing which causes a freeze is if you place a bunch of blocks on a contracted lane so their "expanded" interface is not yet visible, then double-click to expand the lane and thereby expand all the blocks at once. The expanded block controls such as the header and footer and all the envelope stuff is not actually created until the first time they are made visible, so when a bunch of blocks are expanded at once it has to generate all those controls.

From my profiling this appears to be entirely a UI issue, which is good because that means the audio system is not lagging at all. Specifically the bottleneck is Godot's scene instantiation process.

As part of what I'm doing to remedy this I've written a scene pooling system which allows me to keep a buffer of 100 or so block controls for use when they are needed. I can tune this for different types of block to keep a larger buffer of controls ready, and specify when new controls should be created in the background. When a block is deleted the control is put back in the pool for re-use. When a block is created it will bring a control out of the pool to use for its front-end, or create a new control only if the pool is empty. Ideally new blocks will always be able to get a control from the pool. These are just the front-end part of the blocks that you interact with, which up until now have been strongly attached to the actual underlying block object which they control. Now they need to be reusable for different underlying block objects.

When I started looking into this I was wondering if anyone had already addressed the issue of how slow instancing scenes is in Godot and one funny thing I found is if you google for "Godot scene pool" one of the first results is this tweet from the creator of Godot:

https://twitter.com/reduzio/status/1073284242086551552

It's an interesting tweet to say the least because instancing scenes is one of the slowest things you can do in Godot. I guess the word "fast" doesn't mean much unless we know what's being compared. Godot's object instancing is maybe fast compared to Unity in the same way that a snail is fast compared to the tectonic shifting of the Earth's plates. Perhaps in games it is less common to be creating hundreds of dynamic objects in a single frame, so for more common use cases Godot's scene instantiation could be fast enough.

My initial tests after implementing the new scene pool system show an absolutely massive speedup, so the scene instantiation is definitely the bottleneck. I can now create copies of hundreds of blocks at once and it happens pretty much instantly. Hopefully this scales well enough as things become more complex.

When a block is deleted and its control is returned to the pool it now goes into a sort of hibernation mode where it detaches from the block object and turns off all its processing. Then when it is "revived" for use with another block it has to re-attach itself and reactivate. This is not how the controls were originally designed to work at all so I'm currently in the process of unbreaking everything and ensuring the controls can go in and out of hibernation without any problems.


Comments

No comments found for this post.