Skip to content

Commit 30c000b

Browse files
authored
Merge pull request #172 from pjanotti/assorted.perf.changes
Performance improvement during run of instrumented code
2 parents bc85b02 + b9d5e98 commit 30c000b

File tree

5 files changed

+46
-17
lines changed

5 files changed

+46
-17
lines changed

src/coverlet.core/Coverage.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ private void CalculateCoverage()
161161
continue;
162162
}
163163

164+
List<Document> documents = result.Documents.Values.ToList();
165+
164166
using (var fs = new FileStream(result.HitsFilePath, FileMode.Open))
165167
using (var sr = new StreamReader(fs))
166168
{
@@ -173,7 +175,7 @@ private void CalculateCoverage()
173175
continue;
174176

175177
bool isBranch = info[0] == "B";
176-
var document = result.Documents.ElementAt(int.Parse(info[1])).Value;
178+
var document = documents[int.Parse(info[1])];
177179

178180
int start = int.Parse(info[2]);
179181
int hits = int.Parse(info[4]);

src/coverlet.core/Instrumentation/Instrumenter.cs

+4-14
Original file line numberDiff line numberDiff line change
@@ -175,25 +175,20 @@ private void InstrumentIL(MethodDefinition method)
175175

176176
private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, SequencePoint sequencePoint)
177177
{
178-
int documentIndex = 0;
179178
if (!_result.Documents.TryGetValue(sequencePoint.Document.Url, out var document))
180179
{
181180
document = new Document { Path = sequencePoint.Document.Url };
182-
documentIndex = _result.Documents.Count;
181+
document.Index = _result.Documents.Count;
183182
_result.Documents.Add(document.Path, document);
184183
}
185-
else
186-
{
187-
documentIndex = _result.Documents.Keys.ToList().IndexOf(document.Path);
188-
}
189184

190185
for (int i = sequencePoint.StartLine; i <= sequencePoint.EndLine; i++)
191186
{
192187
if (!document.Lines.ContainsKey(i))
193188
document.Lines.Add(i, new Line { Number = i, Class = method.DeclaringType.FullName, Method = method.FullName });
194189
}
195190

196-
string marker = $"L,{documentIndex},{sequencePoint.StartLine},{sequencePoint.EndLine}";
191+
string marker = $"L,{document.Index},{sequencePoint.StartLine},{sequencePoint.EndLine}";
197192

198193
var pathInstr = Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath);
199194
var markInstr = Instruction.Create(OpCodes.Ldstr, marker);
@@ -208,17 +203,12 @@ private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor
208203

209204
private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor processor, Instruction instruction, BranchPoint branchPoint)
210205
{
211-
int documentIndex = 0;
212206
if (!_result.Documents.TryGetValue(branchPoint.Document, out var document))
213207
{
214208
document = new Document { Path = branchPoint.Document };
215-
documentIndex = _result.Documents.Count;
209+
document.Index = _result.Documents.Count;
216210
_result.Documents.Add(document.Path, document);
217211
}
218-
else
219-
{
220-
documentIndex = _result.Documents.Keys.ToList().IndexOf(document.Path);
221-
}
222212

223213
var key = (branchPoint.StartLine, (int)branchPoint.Ordinal);
224214
if (!document.Branches.ContainsKey(key))
@@ -235,7 +225,7 @@ private Instruction AddInstrumentationCode(MethodDefinition method, ILProcessor
235225
}
236226
);
237227

238-
string marker = $"B,{documentIndex},{branchPoint.StartLine},{branchPoint.Ordinal}";
228+
string marker = $"B,{document.Index},{branchPoint.StartLine},{branchPoint.Ordinal}";
239229

240230
var pathInstr = Instruction.Create(OpCodes.Ldstr, _result.HitsFilePath);
241231
var markInstr = Instruction.Create(OpCodes.Ldstr, marker);

src/coverlet.core/Instrumentation/InstrumenterResult.cs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public Document()
2727
}
2828

2929
public string Path;
30+
public int Index;
3031

3132
public Dictionary<int, Line> Lines { get; private set; }
3233
public Dictionary<(int Line, int Ordinal), Branch> Branches { get; private set; }

src/coverlet.tracker/CoverageTracker.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Coverlet.Tracker
88
public static class CoverageTracker
99
{
1010
private static List<Dictionary<string, Dictionary<string, int>>> _events;
11+
private static readonly StringHashSuffixComparer _stringHashSuffixComparer = new StringHashSuffixComparer();
1112

1213
[ThreadStatic]
1314
private static Dictionary<string, Dictionary<string, int>> t_events;
@@ -25,7 +26,7 @@ public static void MarkExecuted(string file, string evt)
2526
{
2627
if (t_events == null)
2728
{
28-
t_events = new Dictionary<string, Dictionary<string, int>>();
29+
t_events = new Dictionary<string, Dictionary<string, int>>(_stringHashSuffixComparer);
2930
lock (_events)
3031
{
3132
_events.Add(t_events);
@@ -38,7 +39,7 @@ public static void MarkExecuted(string file, string evt)
3839
{
3940
if (!t_events.TryGetValue(file, out var fileEvents))
4041
{
41-
fileEvents = new Dictionary<string, int>();
42+
fileEvents = new Dictionary<string, int>(_stringHashSuffixComparer);
4243
t_events.Add(file, fileEvents);
4344
}
4445

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Collections.Generic;
2+
3+
namespace Coverlet.Tracker
4+
{
5+
internal class StringHashSuffixComparer : IEqualityComparer<string>
6+
{
7+
public bool Equals(string x, string y) => string.Equals(x, y);
8+
9+
public int GetHashCode(string s)
10+
{
11+
if (s == null || s.Length == 0)
12+
return 0;
13+
14+
// Hash calculation based on the old implementation of NameTable used in System.Xml
15+
const int SuffixLength = 8;
16+
const int Seed = 1031880390;
17+
int hashCode;
18+
unchecked
19+
{
20+
hashCode = s.Length + Seed;
21+
int i = s.Length > SuffixLength ? s.Length - SuffixLength : 0;
22+
for (; i<s.Length; ++i)
23+
{
24+
hashCode += (hashCode << 7) ^ s[i];
25+
}
26+
27+
hashCode -= hashCode >> 17;
28+
hashCode -= hashCode >> 11;
29+
hashCode -= hashCode >> 5;
30+
}
31+
32+
return hashCode;
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)