-
Notifications
You must be signed in to change notification settings - Fork 662
Sped up the Normalization by removing an unnecessary O(n^2) loop #2990
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
Conversation
| var branchName = remoteTrackingReferenceName.Substring(prefix.Length); | ||
| var localCanonicalName = "refs/heads/" + branchName; | ||
|
|
||
| var referenceName = ReferenceName.Parse(localCanonicalName); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
277fbf1 to
1540fcc
Compare
asbjornu
left a comment
There was a problem hiding this 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?
Agree. It will need a rebase on top of |
1540fcc to
e8cb495
Compare
|
Thanks to you two! I've just rebased my changes :) |
|
Thank you @ni-fgenois for your contribution! |
|
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 |
|
Ok! Is there one planned soon? (as the last one was Nov 15th) |
|
Also, is there anything I can do to help? |
|
I think we can have a release now. |
|
🎉 This issue has been resolved in version 5.8.2 🎉 Your GitReleaseManager bot 📦🚀 |
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, asRefsis already an indexed structure (Dict).Checklist: