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

Sped up the Normalization by removing an unnecessary O(n^2) loop #2990

Merged
merged 1 commit into from
Feb 14, 2022

Conversation

ni-fgenois
Copy link
Contributor

This should speedup the normalization when there are a lot of branches.
The .Any(x => x.Name.Equals(referenceName) was causing an unnecessary O(n^2) loop, as Refs is already an indexed structure (Dict).

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.

@@ -316,11 +316,10 @@ private void CreateOrUpdateLocalBranchesFromRemoteTrackingOnes(string remoteName
var branchName = remoteTrackingReferenceName.Substring(prefix.Length);
var localCanonicalName = "refs/heads/" + branchName;

var referenceName = ReferenceName.Parse(localCanonicalName);
Copy link
Member

Choose a reason for hiding this comment

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

I think this line is needed - we need to parse the localCanonicalName

Copy link
Contributor Author

@ni-fgenois ni-fgenois Feb 8, 2022

Choose a reason for hiding this comment

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

Are you sure? Is the ReferenceName.Parse doing any validation? Because we are not using referenceName anywhere

Copy link
Member

Choose a reason for hiding this comment

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

Yes it does

public static ReferenceName Parse(string canonicalName)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The following validation snippet from ReferenceName.Parse : IsPrefixedBy(canonicalName, LocalBranchPrefix)
will match the constructed string "refs/heads/" + branchName;

What do you think about changing the construction of the string to ReferenceName.LocalBranchPrefix + branchName; instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or adding a factory method ReferenceName.LocalBranch(branchName)?

Copy link
Member

Choose a reason for hiding this comment

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

The point is to get an instance of the class ReferenceName, which implements IComparabale and thus takes care of all reference comparison logic, such as disregarding refs/heads. Why do we only want to compare against only the local canonical name here?

Copy link
Contributor Author

@ni-fgenois ni-fgenois Feb 10, 2022

Choose a reason for hiding this comment

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

@asbjornu
Well, the problem here is actually using the IComparable interface for searching a matching IReference. Doing such a linear lookup leads to O(n) algorithmic complexity, and as we are already within a loop, this leads to a total O(n^2) algorithm complexity.

We should instead use an data structure with logarithmic lookups directly in order to take this first algorithmic complexity down to a O(1), and the whole tjomg to an O(n) algorithmic complexity.

Lucky for us, the IReferenceCollection class does provide such an access (IReference? this[string name] { get; }), but the key of that dictionnary seems to be a CanonicalName.

Copy link
Contributor Author

@ni-fgenois ni-fgenois Feb 10, 2022

Choose a reason for hiding this comment

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

@arturcic I've modified my code so we use a ReferenceName to query the IReferenceCollection structure. And I've added a factory method to ReferenceName

@ni-fgenois ni-fgenois force-pushed the feature/normalization-speedup branch 3 times, most recently from 277fbf1 to 1540fcc Compare February 10, 2022 18:58
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.

I think this now looks like a decent improvement. Thoughts @arturcic?

@arturcic
Copy link
Member

I think this now looks like a decent improvement. Thoughts @arturcic?

Agree. It will need a rebase on top of main and it should be good to go

@ni-fgenois
Copy link
Contributor Author

Thanks to you two! I've just rebased my changes :)

@arturcic arturcic added this to the 5.x milestone Feb 14, 2022
@arturcic arturcic merged commit efddf2f into GitTools:main Feb 14, 2022
@mergify
Copy link
Contributor

mergify bot commented Feb 14, 2022

Thank you @ni-fgenois for your contribution!

@ni-fgenois
Copy link
Contributor Author

@arturcic @asbjornu what is the process to get a new release?

@ni-fgenois ni-fgenois deleted the feature/normalization-speedup branch February 16, 2022 15:52
@arturcic
Copy link
Member

We don't have an exact list of features we want to include in a release, but we try to release every 2 to 3 months if there are enough items fixed/added

@ni-fgenois
Copy link
Contributor Author

Ok! Is there one planned soon? (as the last one was Nov 15th)

@ni-fgenois
Copy link
Contributor Author

Also, is there anything I can do to help?

@arturcic
Copy link
Member

I think we can have a release now.

@arturcic arturcic modified the milestones: 5.x, 5.8.2 Feb 16, 2022
@github-actions
Copy link

🎉 This issue has been resolved in version 5.8.2 🎉
The release is available on:

Your GitReleaseManager bot 📦🚀

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.

3 participants