Skip to content

Conversation

pvanbuijtene
Copy link

@pvanbuijtene pvanbuijtene commented Sep 30, 2025

Description

Reduce the amount of allocations of Commit instances.

Related Issue

#4680

Motivation and Context

After some investigation it turned out that a lot of commits are being re-created during the process of calculating the version.
By implementing a cache for the commits the overall memory consumption went from ~10GB to ~400MB.

How Has This Been Tested?

The solution was tested by running the project again with the changes against the same repository resulting in less memory consumption as shown below.

The problem of the memory usage was internally reported on Linux environments and reproduced on Windows.
My machine has 64GB & 22 logical processors.

Screenshots (if appropriate):

The CPU and Memory consumption before the change, peaking at ~10GB.
before
The CPU and Memory consumption after the change, peaking at ~400MB.
after

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@arturcic arturcic self-requested a review September 30, 2025 15:40
Copy link
Member

@asbjornu asbjornu left a comment

Choose a reason for hiding this comment

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

This looks very promising! 👍🏼

<Compile Include="..\..\src\GitVersion.LibGit2Sharp\Git\CommitCollection.cs">
<Link>Git\CommitCollection.cs</Link>
</Compile>
<Compile Include="..\..\src\GitVersion.LibGit2Sharp\Git\GitCache.cs">
Copy link
Member

Choose a reason for hiding this comment

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

Not sure why these explicit Compile items are needed, as the default value of EnableDefaultCompileItems should be true. Ideas @arturcic? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

these files are linked files into the new-cli solution but part of the current solution

@arturcic
Copy link
Member

arturcic commented Oct 2, 2025

@pvanbuijtene I'm quite happy with the direction you're heading with these changes, I will have a look later as well. Thanks for shared the anonymous repo

@pvanbuijtene pvanbuijtene force-pushed the cache-commits branch 2 times, most recently from 60a70cd to c295a82 Compare October 3, 2025 06:01
@pvanbuijtene
Copy link
Author

As you might have noticed, there are some tests failing.

I think one of the reasons for this is that the cache's life span is longer than you would normally expect I think.

From a CLI perspective you would request the version using GitVersion and you're done.

Within the tests there are complete scenarios being checked and I'm not sure if and how the cache should behave.
Maybe it should be cleared with certain steps, or it should be disabled 🤔

As an example this one, it fails with caching of branches and succeeds without branch caching: https://github.com/GitTools/GitVersion/blob/main/src/GitVersion.Core.Tests/VersionCalculation/NextVersionCalculatorTests.cs#L124

    [Test]
    public void MergeFeatureIntoMainline()
    {
        var configuration = TrunkBasedConfigurationBuilder.New.Build();

        using var fixture = new EmptyRepositoryFixture();
        fixture.MakeACommit();
        fixture.ApplyTag("1.0.0");
        fixture.AssertFullSemver("1.0.0", configuration);

        fixture.BranchTo("feature/foo");
        fixture.MakeACommit();
        fixture.AssertFullSemver("1.1.0-foo.1", configuration);
        fixture.ApplyTag("1.1.0-foo.1");

        fixture.Checkout(MainBranch);
        fixture.MergeNoFF("feature/foo");
        fixture.AssertFullSemver("1.1.0", configuration);
    }

Copy link
Member

@asbjornu asbjornu left a comment

Choose a reason for hiding this comment

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

Within the tests there are complete scenarios being checked and I'm not sure if and how the cache should behave. Maybe it should be cleared with certain steps, or it should be disabled 🤔

As an example this one, it fails with caching of branches and succeeds without branch caching […]

If the cache breaks tests, I'm thinking it might be uncovering a problem with the cache.

Since this PR was originally about caching the Commit class, perhaps we should keep it at that and ensure that works with 100% green tests before we move on with a future followup PR where we attempt to cache even more Git objects?

internal ReferenceCollection(LibGit2Sharp.ReferenceCollection collection, GitCache gitCache)
{
this.innerCollection = collection.NotNull();
this.gitCache = gitCache;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we should ensure that the GitCache isn't null?

Suggested change
this.gitCache = gitCache;
this.gitCache = gitCache.NotNull();

@arturcic
Copy link
Member

arturcic commented Oct 3, 2025

Within the tests there are complete scenarios being checked and I'm not sure if and how the cache should behave. Maybe it should be cleared with certain steps, or it should be disabled 🤔
As an example this one, it fails with caching of branches and succeeds without branch caching […]

If the cache breaks tests, I'm thinking it might be uncovering a problem with the cache.

Since this PR was originally about caching the Commit class, perhaps we should keep it at that and ensure that works with 100% green tests before we move on with a future followup PR where we attempt to cache even more Git objects?

I will try to investigate why those tests are failing as well

@pvanbuijtene
Copy link
Author

Within the tests there are complete scenarios being checked and I'm not sure if and how the cache should behave. Maybe it should be cleared with certain steps, or it should be disabled 🤔
As an example this one, it fails with caching of branches and succeeds without branch caching […]

If the cache breaks tests, I'm thinking it might be uncovering a problem with the cache.

Since this PR was originally about caching the Commit class, perhaps we should keep it at that and ensure that works with 100% green tests before we move on with a future followup PR where we attempt to cache even more Git objects?

Think I would agree with that, caching branches and tags is as you might expect not as straight forward as the commits.

Copy link

sonarqubecloud bot commented Oct 4, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants