Skip to content

Core: Reduce assignments in Variant Object constructor - #121834

Open
aurpine wants to merge 1 commit into
godotengine:masterfrom
aurpine:variant-object-init-no-cleanup
Open

Core: Reduce assignments in Variant Object constructor#121834
aurpine wants to merge 1 commit into
godotengine:masterfrom
aurpine:variant-object-init-no-cleanup

Conversation

@aurpine

@aurpine aurpine commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What problem(s) does this PR solve?

  • Removes redundant assignments in the Variant Object* constructor.

Additional information

  • In the constructor Variant(Object *), ObjData is empty-initialized because ref_pointer unrefs the old value. This is not needed in a constructor so the new implementation extracts the main body from ref_pointer.

@aurpine
aurpine requested a review from a team as a code owner July 27, 2026 19:53

@Ivorforce Ivorforce left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Makes sense, but "Removes redundant assignments" is not a sufficient motivation for a PR.

I assume this is for performance purposes? If yes, we'd need to see some measurements as per our optimization guidelines.
I agree the new code should be faster; the question is if it matters in any practical case (so a profile would be enough for me).

@aurpine

aurpine commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Yes this was identified through GDScript function call profiling. Setup: calling an empty instance function in a loop.

VS2022 Profiling Before:
image

After:
image

However I am unable to get results as high in release templates. Maybe MinGW vs MSVC differences?


In a C++ benchmark, I only notice a difference when build with MSVC. N=100,000,000 Variant constructions 0.73s (PR) vs 1.11s (master).

Test snippet
    const int N = 100'000'000;

    std::vector<Object *> objs;

    for (int i = 0; i < 1024; i++) {
        objs.push_back(memnew(CustomObject));
    }

    auto t = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < N; i++) {
        Variant a(objs[i & 1023]);
        if (!a) { // So the construction doesn't get optimized out
            break;
        }
    }

    auto t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t).count();

    print_line(duration / 1000.);

I am not sure if this is change is desired if GCC already optimizes it. I haven't tested clang/LLVM.

@Ivorforce Ivorforce left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yea, it's possible compilers will be able to reason away most of the code, but I wouldn't always rely on it. MSVC especially isn't very good at it.

We optimize most constructors for this reason, and I think it's warranted to do it here too, since it's a hot path between C++ and Scripts/GDExtension.

@aurpine
aurpine force-pushed the variant-object-init-no-cleanup branch from 96f32d0 to 1343950 Compare July 28, 2026 00:42
@aurpine

aurpine commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Since we aren't calling an ObjData function anymore... we can use memnew_placement like the other constructors. I think &_get_obj() is the same as _data._mem...

This makes the profiling results look even better:
image

Because of the struct initializer list with two arguments, the comma is parsed as part of the macro. The fix I found is to add a comma macro.

Re-requesting review as to not sneak in this substantial change.

@aurpine
aurpine requested a review from Ivorforce July 28, 2026 00:43

@Ivorforce Ivorforce left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Technically more correct than the assignment path.

Comment thread core/variant/variant.cpp Outdated
@aurpine
aurpine force-pushed the variant-object-init-no-cleanup branch from 1343950 to 98ddee4 Compare July 28, 2026 08:48
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.

2 participants