Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase: improve perfs when displaying list of commits #11197

Merged
merged 1 commit into from Sep 15, 2023

Conversation

pmiossec
Copy link
Member

@pmiossec pmiossec commented Sep 7, 2023

by retrieving all the commits data with only one git log call instead of one by commit.
It is possible as when rebasing, all the commits belong to the same branch.

Kept a fall back to previous way to retrieve commit data for 1 commit if commit is not in the one loaded.

Results to show the rebase popup with 7448 commits rebased: 2s instead of 4m50 previously

Fixes #10698 and fixes #11196

Test methodology

  • Manual

Test environment(s)

  • Git Extensions 33.33.33
  • Build acee834 (Dirty)
  • Git 2.42.0.windows.2
  • Microsoft Windows NT 10.0.22621.0
  • .NET 6.0.21
  • DPI 96dpi (no scaling)
  • Portable: False
  • Microsoft.WindowsDesktop.App Versions
    Microsoft.WindowsDesktop.App 6.0.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    Microsoft.WindowsDesktop.App 7.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Merge strategy

I agree that the maintainer squash merge this PR (if the commit message is clear).


✒️ I contribute this code under The Developer Certificate of Origin.

@ghost ghost assigned pmiossec Sep 7, 2023
@pmiossec
Copy link
Member Author

pmiossec commented Sep 7, 2023

@dosercz You could try the portable version here: https://ci.appveyor.com/project/gitextensions/gitextensions/build/artifacts

Copy link
Member

@gerhardol gerhardol left a comment

Choose a reason for hiding this comment

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

+1
Has not run

GitCommands/RevisionReader.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
Copy link
Member

@gerhardol gerhardol left a comment

Choose a reason for hiding this comment

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

Approving, assuming the question is fixed

{
Author = data?.Author,
ObjectId = data?.ObjectId,
Subject = data?.Body,
Copy link
Member

Choose a reason for hiding this comment

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

Is body or Subject needed?
RevisionReader will not save Body (just subject) if the commit is older than 6 months.
(rename the _sixMonths variable to _oldestBody?)

        public RevisionReader(GitModule module, bool hasReflogSelector, bool allBodies = false)
            : this(module, hasReflogSelector, module.LogOutputEncoding, allBodies ? 0 : new DateTimeOffset(DateTime.Now.ToUniversalTime() - TimeSpan.FromDays(30 * 6)).ToUnixTimeSeconds())
        {
        }

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Subject = data?.Body,
Subject = error ?? data?.Subject,

Copy link
Member

Choose a reason for hiding this comment

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

If the Body is not needed, then those changes in RevisionReader is not required, just enough to clarify with this line.
(I do not mind keep them, should be used later).

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

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

Few nits and suggestions

GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Show resolved Hide resolved
GitCommands/RevisionReader.cs Outdated Show resolved Hide resolved
@RussKie RussKie added the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Sep 10, 2023
@ghost ghost removed the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Sep 12, 2023
@dosercz
Copy link

dosercz commented Sep 12, 2023

@pmiossec I have tested portable version builded for this PR and it's fine, good job. It'll safe a lot of my time!

@pmiossec
Copy link
Member Author

pmiossec commented Sep 12, 2023

@gerhardol Could you give your point of view at least on the 2nd commit that get the bodies for older commits as I did some refactoring/renaming?

var isApplying = currentCommitShortHash is not null && commitHash.StartsWith(currentCommitShortHash);
isCurrentFound |= isApplying;
RevisionReader reader = new(this, hasReflogSelector: false, allBodies: true);
CancellationTokenSource cts = new(2 * 60_000);
Copy link
Member

Choose a reason for hiding this comment

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

A comment here would be great as well. This is two minutes? Why so long?

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
CancellationTokenSource cts = new(2 * 60_000);
CancellationTokenSource cts = new(TimeSpan.FromMinutes(2));

or whatever value how long we would block the UI if there are extremely many commits.

Copy link
Member

Choose a reason for hiding this comment

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

Hopefully two minutes will no longer be needed, but if there is a scenario where the new handling is not effective, keep it.

@RussKie
Copy link
Member

RussKie commented Sep 12, 2023

👍

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

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

just tuning


string[] parts = todoCommit.Split(Delimiters.Space);
// Filter comment lines and keep only lines containing at least 3 columns
// (action, commit hash and commit subject -- that could contains space and be cut in more --)
Copy link
Member

Choose a reason for hiding this comment

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

nit:

Suggested change
// (action, commit hash and commit subject -- that could contains space and be cut in more --)
// (action, commit hash and commit subject -- that could contain spaces and be cut in more --)

var isApplying = currentCommitShortHash is not null && commitHash.StartsWith(currentCommitShortHash);
isCurrentFound |= isApplying;
RevisionReader reader = new(this, hasReflogSelector: false, allBodies: true);
CancellationTokenSource cts = new(2 * 60_000);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
CancellationTokenSource cts = new(2 * 60_000);
CancellationTokenSource cts = new(TimeSpan.FromMinutes(2));

or whatever value how long we would block the UI if there are extremely many commits.

GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
GitCommands/RevisionReader.cs Show resolved Hide resolved
GitCommands/RevisionReader.cs Outdated Show resolved Hide resolved
Copy link
Member

@gerhardol gerhardol left a comment

Choose a reason for hiding this comment

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

agree with most other comments, assume they will be resolved

GitCommands/RevisionReader.cs Outdated Show resolved Hide resolved
{
Author = data?.Author,
ObjectId = data?.ObjectId,
Subject = data?.Body,
Copy link
Member

Choose a reason for hiding this comment

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

If the Body is not needed, then those changes in RevisionReader is not required, just enough to clarify with this line.
(I do not mind keep them, should be used later).

var isApplying = currentCommitShortHash is not null && commitHash.StartsWith(currentCommitShortHash);
isCurrentFound |= isApplying;
RevisionReader reader = new(this, hasReflogSelector: false, allBodies: true);
CancellationTokenSource cts = new(2 * 60_000);
Copy link
Member

Choose a reason for hiding this comment

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

Hopefully two minutes will no longer be needed, but if there is a scenario where the new handling is not effective, keep it.

GitCommands/Git/GitModule.cs Show resolved Hide resolved
Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

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

👍

@@ -2151,7 +2151,7 @@ public IReadOnlyList<PatchFile> GetInteractiveRebasePatchFiles()
string commentChar = EffectiveConfigFile.GetString("core.commentChar", "#");

// Filter comment lines and keep only lines containing at least 3 columns
// (action, commit hash and commit subject -- that could contains space and be cut in more --)
// (action, commit hash and commit subject -- that could contains spaces and be cut in more --)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// (action, commit hash and commit subject -- that could contains spaces and be cut in more --)
// (action, commit hash and commit subject -- that could contain spaces and be cut in more --)

isCurrentFound |= isApplying;
// retrieve commits bodies to display them in the grid or as tooltips
RevisionReader reader = new(this, hasReflogSelector: false, allBodies: true);
CancellationTokenSource cts = new(TimeSpan.FromSeconds(15));
Copy link
Member

Choose a reason for hiding this comment

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

This might be too short. It can take a few seconds for a few commits on a workstation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it something you saw?
Because, in GE repo, I made a rebase of 12k commits and it took only 250ms that's why I concluded that in this case 15s was enough. But I have no problem to increase it. 30s?

Copy link
Member

Choose a reason for hiding this comment

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

git-log+parsing requires about 2 s for 100K commits so rebasing all commits in the linux repo would require 20s or so on my machine. 30s is safe

The git-rebase operation can require some time though

Copy link
Member Author

Choose a reason for hiding this comment

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

The cancelation token is only for the 'git log & parsing' so I'm happy you confirm that 15s is enough (to rebase 700k commits!) 🤣
But secured 30s is OK for me as we are talking about a worst case scenario that will nearly never happen...

Copy link
Member

Choose a reason for hiding this comment

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

Is it something you saw?

Yes, perhaps caused by hyperactive enterprise AV and / or Windows Update.

(Also git itself became quirky later yesterday. It reproducibly returned exit code 128 without error output when resetting single files using git checkout - vanished after reboot.)

GitCommands/Git/GitModule.cs Outdated Show resolved Hide resolved
isCurrentFound |= isApplying;
// retrieve commits bodies to display them in the grid or as tooltips
RevisionReader reader = new(this, hasReflogSelector: false, allBodies: true);
CancellationTokenSource cts = new(TimeSpan.FromSeconds(15));
Copy link
Member

Choose a reason for hiding this comment

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

Is it something you saw?

Yes, perhaps caused by hyperactive enterprise AV and / or Windows Update.

(Also git itself became quirky later yesterday. It reproducibly returned exit code 128 without error output when resetting single files using git checkout - vanished after reboot.)

@pmiossec
Copy link
Member Author

Do you still want to review something or I could squash and rebase everything?

Copy link
Member

@mstv mstv left a comment

Choose a reason for hiding this comment

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

👍

by retrieving all the commits data with only one `git log` call
instead of one by commit.
It is possible as when rebasing, all the commits belong to the same branch.

Kept a fall back to previous way to retrieve commit data for 1 commit
if commit is not in the one loaded.

and read bodies of all rebased commits
(even the ones older than 6 monthes like it was the case before.
RevisionReader had to be adapted to do that.)

Results with 7448 commits rebased: 2s instead of 4m50 previously

Fixes gitextensions#10698 and gitextensions#11196
@pmiossec
Copy link
Member Author

pmiossec commented Sep 14, 2023

Squashed and rebased. Ready to be merged...

@pmiossec pmiossec merged commit e9d2885 into gitextensions:master Sep 15, 2023
4 checks passed
@ghost ghost added this to the vNext milestone Sep 15, 2023
@pmiossec pmiossec deleted the improve_perf_rebase branch September 15, 2023 11:02
GitArgumentBuilder arguments = new("log")
{
"-z",
$"--pretty=format:\"{FullFormat}\"",
Copy link
Member

Choose a reason for hiding this comment

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

This should have been LogFormat, will change at another update

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