Skip to content

Introduce a cache to improve performance of construction of SDFormat#1610

Merged
azeey merged 6 commits intosdf16from
arjo/fix/cache_perf
Jan 2, 2026
Merged

Introduce a cache to improve performance of construction of SDFormat#1610
azeey merged 6 commits intosdf16from
arjo/fix/cache_perf

Conversation

@arjo129
Copy link
Copy Markdown
Contributor

@arjo129 arjo129 commented Dec 29, 2025

🦟 Bug fix

Fixes #1478

Summary

This commit should reduce load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

On my m4 macbook air this reduces the following benchmark:

#include <sdf/Model.hh>
#include <sdf/Root.hh>

void deserialize()
{
    std::string sdf = "<?xml version=\"1.0\" ?><sdf version='1.6'></sdf>";
    sdf::Root root;
    sdf::Errors errors = root.LoadSdfString(sdf);
    if (!root.Model())
    {
        return;
    }
    sdf::Model _model = *root.Model();
    return;
}

int main(int argc, char **argv)
{
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    for (int i = 0; i < 100; i++)
    deserialize();
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

    std::cout << "Whole function call took: " <<
        std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()
        << "[µs]" << std::endl;
}

from running for 300000µs to 3000µs.

Checklist

  • Signed all commits for DCO
  • Added tests
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers
  • Was GenAI used to generate this PR? If so, make sure to add "Generated-by" to your commits. (See this policy for more info.)

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by and Generated-by messages.

This commit should reduce load times significantly as it caches the first parse of the spec
so that it does not need to be reparsed at library load time through static initiallization of a pass.

On my m4 macbook air this reduces the following benchmark:

void deserialize()
{
    std::string sdf = "<?xml version=\"1.0\" ?><sdf version='1.6'></sdf>";
    sdf::Root root;
    sdf::Errors errors = root.LoadSdfString(sdf);
    if (!root.Model())
    {
        return;
    }
    sdf::Model _model = *root.Model();
    return;
}

int main(int argc, char **argv)
{
    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    for (int i = 0; i < 100; i++)
    deserialize();
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

    std::cout << "Whole function call took: " <<
        std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()
        << "[µs]" << std::endl;
}

from running for 300000µs to 3000µs.

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
@arjo129 arjo129 force-pushed the arjo/fix/cache_perf branch from 69c70c1 to 60107a5 Compare December 29, 2025 01:09
Copy link
Copy Markdown
Contributor

@iche033 iche033 left a comment

Choose a reason for hiding this comment

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

nice, this should replace gazebosim/gz-sim#3082

Comment thread include/sdf/SDFImpl.hh
Comment thread src/SDFImplPrivate.hh
- Add copy constructor unit tests
- Add doxygen comments

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
@arjo129 arjo129 changed the base branch from sdf16 to main December 30, 2025 05:45
@arjo129 arjo129 changed the base branch from main to sdf16 December 30, 2025 05:45
@arjo129
Copy link
Copy Markdown
Contributor Author

arjo129 commented Dec 30, 2025

Before I merge this, I think its worth pointing out that I think this breaks ABI (thanks to adding a copy constructor), in which case I should re-target this to main and we release these improvements in Kura. I am not 100% sure. According to KDE's guidelines adding new constructors is non-ABI breaking, however imo adding a copy constructor after-the fact may break ABI as the compilers might assume default copy for older versions. I think if someone can enlighten me as to whether my suspicion is right or wrong, I will retarget this PR accordingly.

Comment thread src/Root.cc Outdated
@github-project-automation github-project-automation bot moved this from Inbox to In review in Core development Dec 30, 2025
@azeey
Copy link
Copy Markdown
Collaborator

azeey commented Dec 30, 2025

That's a great speed up!! Thanks for looking into it. We already do something like this in parser.cc for handling include tags :

sdformat/src/parser.cc

Lines 1741 to 1751 in 9c1bd31

// NOTE: sdf::init is an expensive call. For performance reason,
// a new sdf pointer is created here by cloning a fresh sdf template
// pointer instead of calling init every iteration.
// SDFPtr includeSDF(new SDF);
// init(includeSDF, _config);
static SDFPtr includeSDFTemplate;
if (!includeSDFTemplate)
{
includeSDFTemplate.reset(new SDF);
init(includeSDFTemplate, _config);
}

So the approach is sound.

Before I merge this, I think its worth pointing out that I think this breaks ABI (thanks to adding a copy constructor), in which case I should re-target this to main and we release these improvements in Kura. I am not 100% sure. According to KDE's guidelines adding new constructors is non-ABI breaking, however imo adding a copy constructor after-the fact may break ABI as the compilers might assume default copy for older versions. I think if someone can enlighten me as to whether my suspicion is right or wrong, I will retarget this PR accordingly.

I don't think it breaks ABI because the compiler generates the copy constructor inside the shared library. From the binary symbol perspective, defining a new copy constructor here just means we're changing the behavior of the existing copy constructor. You can see the generated code on godbolt by commenting out the custom copy constructor: https://godbolt.org/z/4cjddMeTd

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
@arjo129
Copy link
Copy Markdown
Contributor Author

arjo129 commented Dec 31, 2025

Thanks for the clarification!

I've resorted to using gz::utils::NeverDestroy.

Comment thread src/Root.cc Outdated
Comment thread src/Root.cc
arjo129 and others added 2 commits December 31, 2025 16:33
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
@azeey azeey merged commit 403d96a into sdf16 Jan 2, 2026
16 checks passed
@azeey azeey deleted the arjo/fix/cache_perf branch January 2, 2026 16:24
@github-project-automation github-project-automation bot moved this from In review to Done in Core development Jan 2, 2026
@azeey
Copy link
Copy Markdown
Collaborator

azeey commented Jan 2, 2026

@Mergifyio backport main sdf15 sdf14 sdf12

@mergify
Copy link
Copy Markdown
Contributor

mergify bot commented Jan 2, 2026

backport main sdf15 sdf14 sdf12

✅ Backports have been created

Details

mergify bot pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
mergify bot pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
mergify bot pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
mergify bot pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)

# Conflicts:
#	src/SDF_TEST.cc
azeey pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
azeey pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
azeey pushed a commit that referenced this pull request Jan 2, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)
azeey pushed a commit that referenced this pull request Jan 9, 2026
…1610)

Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache.

---------

Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org>
Signed-off-by: Arjo Chakravarty <arjo129@gmail.com>
Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
(cherry picked from commit 403d96a)

# Conflicts:
#	src/SDF_TEST.cc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🪵 jetty Gazebo Jetty

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Poor performance of SDF Element Pointer Construction

3 participants