+1 vote

I'm getting a huge hitch on loading a scene (10 seconds in editor) using an asynchronous loading module.

It's an asset that when preloaded into the scene the simple and synchronous way makes the play in editor take 10 seconds to launch, so I'm trying to be more responsive by loading in background.

This part flies like a breeze (the actual loading, on another thread):

godot::Ref<godot::PackedScene> scene = godot::ResourceLoader::get_singleton()->load(hullPath, "PackedScene");
godot::Node* spaceship = scene->instance();

Then this takes ten seconds (since the node is already loaded and instanced, I'd assume it would be fast... this is called synchronously):

godot::Node* finalNode = nodeFuture.get();
if (finalNode->is_class("Spatial")) {
    ((godot::Spatial*) finalNode)->set_transform(startingTransform);

I'd assume that the most time would be consumed by the "load" call. But it's the addition to the tree that creates the huge slowdown.

What can be done from the loading thread for it to bear those 10 seconds instead of the main thread?

in Engine by (17 points)

1 Answer

+1 vote

To sum it up:

  • Loading resources in a thread should be fine.
  • Instancing a scene... I'm not sure but I don't see what could go wrong since it remains pretty isolated.
  • Adding to the tree: nope.

Make sure your visual, audio and physics servers are configured in such a way their API is thread-safe (at least don't set them to be "single-unsafe").

Assuming thread safety is respected, the slowness could come from mainly two factors:

  • There is an absurd amount of nodes as child of the branch you are adding
  • Something is executing in ENTER_TREE or READY notification of the nodes you are adding, and that thing has to deal with a huge amount of data/operations (or queries to visual or physics server)

Hard to say how to proceed without knowing which one is going on. You may want to narrow down your profiling a bit further.

by (27,831 points)
edited by

I'm not adding to the scene tree from a thread. The inclusion to the tree is the only thing that I'm doing in the main thread (second code bit). I'll investigate further, it's probably my fault but I don't see where.
When I'm back home I'll test if the ready function is the culprit, it's my main suspect.

I was indeed doing some heavy work on the ready override. I've moved it to the init override, but the hang still stands for it's well over 10 seconds. I suspect std::future and std::promise lock, even using the std::future::wait-for(0) recommended by everyone.

What is the heavy work?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.