Skip to content

Commit d8baaa6

Browse files
authored
Merge pull request #1838 from erikbra/feature/performance-improvements
Performance improvements - profiling and simple caching
2 parents 41e0152 + f480a3a commit d8baaa6

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

src/GitVersionCore.Tests/Mocks/MockRepository.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public void RevParse(string revision, out Reference reference, out GitObject obj
211211

212212
public Branch Head { get; set; }
213213
public LibGit2Sharp.Configuration Config { get; set; }
214-
public Index Index { get; set; }
214+
public LibGit2Sharp.Index Index { get; set; }
215215
public ReferenceCollection Refs { get; set; }
216216

217217
public IQueryableCommitLog Commits

src/GitVersionCore/IncrementStrategyFinder.cs

+39-12
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,16 @@ public static class IncrementStrategyFinder
6969

7070
public static VersionField? GetIncrementForCommits(GitVersionContext context, IEnumerable<Commit> commits)
7171
{
72-
var majorRegex = CreateRegex(context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern);
73-
var minorRegex = CreateRegex(context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern);
74-
var patchRegex = CreateRegex(context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern);
75-
var none = CreateRegex(context.Configuration.NoBumpMessage ?? DefaultNoBumpPattern);
72+
// More efficient use of Regexes. The static version of Regex.IsMatch caches the compiled regexes.
73+
// see: https://docs.microsoft.com/en-us/dotnet/standard/base-types/best-practices#static-regular-expressions
74+
75+
var majorRegex = context.Configuration.MajorVersionBumpMessage ?? DefaultMajorPattern;
76+
var minorRegex = context.Configuration.MinorVersionBumpMessage ?? DefaultMinorPattern;
77+
var patchRegex = context.Configuration.PatchVersionBumpMessage ?? DefaultPatchPattern;
78+
var none = context.Configuration.NoBumpMessage ?? DefaultNoBumpPattern;
7679

7780
var increments = commits
78-
.Select(c => FindIncrementFromMessage(c.Message, majorRegex, minorRegex, patchRegex, none))
81+
.Select(c => GetIncrementFromMessage(c.Message, majorRegex, minorRegex, patchRegex, none))
7982
.Where(v => v != null)
8083
.Select(v => v.Value)
8184
.ToList();
@@ -88,6 +91,8 @@ public static class IncrementStrategyFinder
8891
return null;
8992
}
9093

94+
95+
9196
private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Commit baseCommit, Commit headCommit)
9297
{
9398
if (baseCommit == null) yield break;
@@ -114,21 +119,43 @@ private static IEnumerable<Commit> GetIntermediateCommits(IRepository repo, Comm
114119
}
115120
}
116121

117-
private static VersionField? FindIncrementFromMessage(string message, Regex major, Regex minor, Regex patch, Regex none)
122+
private static VersionField? GetIncrementFromMessage(string message, string majorRegex, string minorRegex, string patchRegex, string none)
118123
{
119-
if (major.IsMatch(message)) return VersionField.Major;
120-
if (minor.IsMatch(message)) return VersionField.Minor;
121-
if (patch.IsMatch(message)) return VersionField.Patch;
122-
if (none.IsMatch(message)) return VersionField.None;
124+
var key = message.GetHashCode();
125+
126+
if (!VersionFieldCache.TryGetValue(key, out var version))
127+
{
128+
version = FindIncrementFromMessage(message, majorRegex, minorRegex, patchRegex, none);
129+
VersionFieldCache[key] = version;
130+
}
131+
return version;
132+
}
123133

134+
135+
private static VersionField? FindIncrementFromMessage(string message, string majorRegex, string minorRegex, string patchRegex, string noneRegex)
136+
{
137+
if(IsMatch(message, majorRegex)) return VersionField.Major;
138+
if(IsMatch(message, minorRegex)) return VersionField.Minor;
139+
if(IsMatch(message, patchRegex)) return VersionField.Patch;
140+
if(IsMatch(message, noneRegex)) return VersionField.None;
124141
return null;
125142
}
126143

127-
private static Regex CreateRegex(string pattern)
144+
private static bool IsMatch(string message, string regex)
128145
{
129-
return new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
146+
var key = message.GetHashCode() ^ regex.GetHashCode();
147+
148+
if (!MatchCache.TryGetValue(key, out var match))
149+
{
150+
match = Regex.IsMatch(message, regex, RegexOptions.IgnoreCase);
151+
MatchCache[key] = match;
152+
}
153+
return match;
130154
}
131155

156+
private static IDictionary<int, bool> MatchCache = new Dictionary<int, bool>();
157+
private static IDictionary<int, VersionField?> VersionFieldCache = new Dictionary<int, VersionField?>();
158+
132159
public static VersionField FindDefaultIncrementForBranch( GitVersionContext context, string branch = null )
133160
{
134161
var config = context.FullConfiguration.GetConfigForBranch(branch ?? context.CurrentBranch.NameWithoutRemote());

src/GitVersionCore/VersionCalculation/BaseVersionCalculators/BaseVersion.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ public override string ToString()
3131
return $"{Source}: {SemanticVersion.ToString("f")} with commit count source {(BaseVersionSource == null ? "External Source" : BaseVersionSource.Sha)} (Incremented: {(ShouldIncrement ? BaseVersionCalculator.MaybeIncrement(_context, this).ToString("t") : "None")})";
3232
}
3333
}
34-
}
34+
}

0 commit comments

Comments
 (0)