From 45bfffeab7276338b76cebc6dbd38121fbdbab42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janusz=20Bia=C5=82obrzewski?= Date: Wed, 21 Nov 2018 13:29:42 +0100 Subject: [PATCH] Improve time complexity of IndexOf. The complexity was O(n), which is not acceptable for a method that is used to compare elements in a sorting algorithm. The new time complexity is O(1). --- GitUI/CommitInfo/CommitInfo.cs | 54 +++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/GitUI/CommitInfo/CommitInfo.cs b/GitUI/CommitInfo/CommitInfo.cs index 1200b0ddf02..5961b06b5cf 100644 --- a/GitUI/CommitInfo/CommitInfo.cs +++ b/GitUI/CommitInfo/CommitInfo.cs @@ -78,7 +78,7 @@ public partial class CommitInfo : GitModuleControl private List _branches; private string _branchInfo; private string _gitDescribeInfo; - [CanBeNull] private IList _sortedRefs; + [CanBeNull] private IDictionary _refsOrderDict; private int _revisionInfoHeight; private int _commitMessageHeight; @@ -227,7 +227,7 @@ void StartAsyncDataLoad() ThreadHelper.JoinableTaskFactory.RunAsync(() => LoadLinksForRevisionAsync(_revision)).FileAndForget(); - if (_sortedRefs == null) + if (_refsOrderDict == null) { ThreadHelper.JoinableTaskFactory.RunAsync(() => LoadSortedRefsAsync()).FileAndForget(); } @@ -295,10 +295,21 @@ string GetLinksForRevision() async Task LoadSortedRefsAsync() { await TaskScheduler.Default.SwitchTo(alwaysYield: true); - _sortedRefs = Module.GetSortedRefs().ToList(); + _refsOrderDict = ToDictionary(Module.GetSortedRefs()); await this.SwitchToMainThreadAsync(cancellationToken); UpdateRevisionInfo(); + + IDictionary ToDictionary(IReadOnlyList list) + { + var dict = new Dictionary(); + for (int i = 0; i < list.Count; i++) + { + dict.Add(list[i], i); + } + + return dict; + } } async Task LoadAnnotatedTagInfoAsync(IReadOnlyList refs) @@ -429,7 +440,7 @@ string GetDescribeInfoForRevision() private void UpdateRevisionInfo() { - if (_sortedRefs != null) + if (_refsOrderDict != null) { if (_annotatedTagsMessages != null && _annotatedTagsMessages.Count > 0 && @@ -445,13 +456,13 @@ private void UpdateRevisionInfo() .Select(r => r.LocalName) .ToList(); - thisRevisionTagNames.Sort(new ItemTpComparer(_sortedRefs, "refs/tags/")); + thisRevisionTagNames.Sort(new ItemTpComparer(_refsOrderDict, "refs/tags/")); _annotatedTagsInfo = GetAnnotatedTagsInfo(thisRevisionTagNames, _annotatedTagsMessages); } if (_tags != null && string.IsNullOrEmpty(_tagInfo)) { - _tags.Sort(new ItemTpComparer(_sortedRefs, "refs/tags/")); + _tags.Sort(new ItemTpComparer(_refsOrderDict, "refs/tags/")); if (_tags.Count > MaximumDisplayedRefs) { _tags[MaximumDisplayedRefs - 2] = "…"; @@ -464,7 +475,7 @@ private void UpdateRevisionInfo() if (_branches != null && string.IsNullOrEmpty(_branchInfo)) { - _branches.Sort(new ItemTpComparer(_sortedRefs, "refs/heads/")); + _branches.Sort(new ItemTpComparer(_refsOrderDict, "refs/heads/")); if (_branches.Count > MaximumDisplayedRefs) { _branches[MaximumDisplayedRefs - 2] = "…"; @@ -711,12 +722,12 @@ protected override void DisposeCustomResources() private sealed class ItemTpComparer : IComparer { - private readonly IList _otherList; + private readonly IDictionary _orderDict; private readonly string _prefix; - public ItemTpComparer(IList otherList, string prefix) + public ItemTpComparer(IDictionary orderDict, string prefix) { - _otherList = otherList; + _orderDict = orderDict; _prefix = prefix; } @@ -726,21 +737,18 @@ public int Compare(string a, string b) int IndexOf(string s) { - var head = s.StartsWith("remotes/") ? "refs/" : _prefix; - var tail = s; - var headLength = head.Length; - var length = headLength + s.Length; - - for (var i = 0; i < _otherList.Count; i++) + if (s.StartsWith("remotes/")) { - var other = _otherList[i]; + s = "refs/" + s; + } + else + { + s = _prefix + s; + } - if (other.Length == length && - other.StartsWith(head) && - other.IndexOf(tail, headLength) == headLength) - { - return i; - } + if (_orderDict.TryGetValue(s, out var index)) + { + return index; } return -1;