Skip to content

Commit fa3a3e2

Browse files
author
Bart Koelman
committed
Added options to exclude time spent in external libraries
1 parent 4f38789 commit fa3a3e2

9 files changed

+61
-22
lines changed

src/JsonApiDotNetCore/Diagnostics/CascadingCodeTimer.cs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,23 @@ static CascadingCodeTimer()
3333
Thread.CurrentThread.Priority = ThreadPriority.Highest;
3434
}
3535

36-
public IDisposable Measure(string name)
36+
/// <inheritdoc />
37+
public IDisposable Measure(string name, bool excludeInRelativeCost = false)
3738
{
38-
MeasureScope childScope = CreateChildScope(name);
39+
MeasureScope childScope = CreateChildScope(name, excludeInRelativeCost);
3940
_activeScopeStack.Push(childScope);
4041

4142
return childScope;
4243
}
4344

44-
private MeasureScope CreateChildScope(string name)
45+
private MeasureScope CreateChildScope(string name, bool excludeInRelativeCost)
4546
{
4647
if (_activeScopeStack.TryPeek(out MeasureScope topScope))
4748
{
48-
return topScope.SpawnChild(this, name);
49+
return topScope.SpawnChild(this, name, excludeInRelativeCost);
4950
}
5051

51-
return new MeasureScope(this, name);
52+
return new MeasureScope(this, name, excludeInRelativeCost);
5253
}
5354

5455
private void Close(MeasureScope scope)
@@ -66,6 +67,7 @@ private void Close(MeasureScope scope)
6667
}
6768
}
6869

70+
/// <inheritdoc />
6971
public string GetResult()
7072
{
7173
var builder = new StringBuilder();
@@ -99,14 +101,16 @@ private sealed class MeasureScope : IDisposable
99101
{
100102
private readonly CascadingCodeTimer _owner;
101103
private readonly IList<MeasureScope> _children = new List<MeasureScope>();
104+
private readonly bool _excludeInRelativeCost;
102105
private readonly TimeSpan _startedAt;
103106
private TimeSpan? _stoppedAt;
104107

105108
public string Name { get; }
106109

107-
public MeasureScope(CascadingCodeTimer owner, string name)
110+
public MeasureScope(CascadingCodeTimer owner, string name, bool excludeInRelativeCost)
108111
{
109112
_owner = owner;
113+
_excludeInRelativeCost = excludeInRelativeCost;
110114
Name = name;
111115

112116
EnsureRunning();
@@ -121,9 +125,9 @@ private void EnsureRunning()
121125
}
122126
}
123127

124-
public MeasureScope SpawnChild(CascadingCodeTimer owner, string name)
128+
public MeasureScope SpawnChild(CascadingCodeTimer owner, string name, bool excludeInRelativeCost)
125129
{
126-
var childScope = new MeasureScope(owner, name);
130+
var childScope = new MeasureScope(owner, name, excludeInRelativeCost);
127131
_children.Add(childScope);
128132
return childScope;
129133
}
@@ -151,23 +155,47 @@ private TimeSpan GetElapsedInChildren()
151155
return elapsedInChildren;
152156
}
153157

158+
private TimeSpan GetSkippedInTotal()
159+
{
160+
TimeSpan skippedInSelf = _excludeInRelativeCost ? GetElapsedInSelf() : TimeSpan.Zero;
161+
TimeSpan skippedInChildren = GetSkippedInChildren();
162+
163+
return skippedInSelf + skippedInChildren;
164+
}
165+
166+
private TimeSpan GetSkippedInChildren()
167+
{
168+
TimeSpan skippedInChildren = TimeSpan.Zero;
169+
170+
foreach (MeasureScope childScope in _children)
171+
{
172+
skippedInChildren += childScope.GetSkippedInTotal();
173+
}
174+
175+
return skippedInChildren;
176+
}
177+
154178
public void WriteResult(StringBuilder builder, int indent)
155179
{
156-
TimeSpan timeElapsedGlobal = GetElapsedInTotal();
180+
TimeSpan timeElapsedGlobal = GetElapsedInTotal() - GetSkippedInTotal();
157181
WriteResult(builder, indent, timeElapsedGlobal);
158182
}
159183

160184
private void WriteResult(StringBuilder builder, int indent, TimeSpan timeElapsedGlobal)
161185
{
162186
TimeSpan timeElapsedInSelf = GetElapsedInSelf();
163-
double scaleElapsedInSelf = timeElapsedInSelf / timeElapsedGlobal;
187+
double scaleElapsedInSelf = timeElapsedGlobal != TimeSpan.Zero ? timeElapsedInSelf / timeElapsedGlobal : 0;
164188

165189
WriteIndent(builder, indent);
166190
builder.Append(Name);
167191
builder.Append(": ");
168192
builder.Append(timeElapsedInSelf.ToString("G", CultureInfo.InvariantCulture));
169-
builder.Append(" - ");
170-
builder.Append(scaleElapsedInSelf.ToString("P", CultureInfo.InvariantCulture));
193+
194+
if (!_excludeInRelativeCost)
195+
{
196+
builder.Append(" - ");
197+
builder.Append(scaleElapsedInSelf.ToString("P", CultureInfo.InvariantCulture));
198+
}
171199

172200
if (_stoppedAt == null)
173201
{

src/JsonApiDotNetCore/Diagnostics/ConsoleDemo.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#if DEBUG
2-
32
using System;
43
using System.Threading.Tasks;
54

@@ -72,5 +71,4 @@ private static async Task SerializeResponseAsync()
7271
}
7372
}
7473
}
75-
7674
#endif

src/JsonApiDotNetCore/Diagnostics/DisabledCodeTimer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ private DisabledCodeTimer()
1515
{
1616
}
1717

18-
public IDisposable Measure(string name)
18+
public IDisposable Measure(string name, bool excludeInRelativeCost = false)
1919
{
2020
return this;
2121
}

src/JsonApiDotNetCore/Diagnostics/ICodeTimer.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ public interface ICodeTimer : IDisposable
1414
/// <param name="name">
1515
/// Description of what is being recorded.
1616
/// </param>
17-
IDisposable Measure(string name);
17+
/// <param name="excludeInRelativeCost">
18+
/// When set, indicates to exclude this measurement in calculated percentages. <c>false</c> by default.
19+
/// </param>
20+
IDisposable Measure(string name, bool excludeInRelativeCost = false);
1821

1922
/// <summary>
2023
/// Returns intermediate or final results.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma warning disable AV1008 // Class should not be static
2+
3+
namespace JsonApiDotNetCore.Diagnostics
4+
{
5+
internal static class MeasurementConstants
6+
{
7+
public static readonly bool ExcludeEfCoreInPercentages = bool.Parse(bool.FalseString);
8+
public static readonly bool ExcludeNewtonsoftJsonInPercentages = bool.Parse(bool.FalseString);
9+
}
10+
}

src/JsonApiDotNetCore/Repositories/EntityFrameworkCoreRepository.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public virtual async Task<IReadOnlyCollection<TResource>> GetAsync(QueryLayer la
7777
{
7878
IQueryable<TResource> query = ApplyQueryLayer(layer);
7979

80-
using (CodeTimingSessionManager.Current.Measure("Execute SQL (data)"))
80+
using (CodeTimingSessionManager.Current.Measure("Execute SQL (data)", MeasurementConstants.ExcludeEfCoreInPercentages))
8181
{
8282
return await query.ToListAsync(cancellationToken);
8383
}
@@ -103,7 +103,7 @@ public virtual async Task<int> CountAsync(FilterExpression topFilter, Cancellati
103103

104104
IQueryable<TResource> query = ApplyQueryLayer(layer);
105105

106-
using (CodeTimingSessionManager.Current.Measure("Execute SQL (count)"))
106+
using (CodeTimingSessionManager.Current.Measure("Execute SQL (count)", MeasurementConstants.ExcludeEfCoreInPercentages))
107107
{
108108
return await query.CountAsync(cancellationToken);
109109
}
@@ -563,7 +563,7 @@ protected virtual async Task SaveChangesAsync(CancellationToken cancellationToke
563563
{
564564
cancellationToken.ThrowIfCancellationRequested();
565565

566-
using (CodeTimingSessionManager.Current.Measure("Persist EF Core changes"))
566+
using (CodeTimingSessionManager.Current.Measure("Persist EF Core changes", MeasurementConstants.ExcludeEfCoreInPercentages))
567567
{
568568
try
569569
{

src/JsonApiDotNetCore/Serialization/BaseDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected object DeserializeBody(string body)
6262
{
6363
ArgumentGuard.NotNullNorEmpty(body, nameof(body));
6464

65-
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Deserialize"))
65+
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Deserialize", MeasurementConstants.ExcludeNewtonsoftJsonInPercentages))
6666
{
6767
JToken bodyJToken = LoadJToken(body);
6868
Document = bodyJToken.ToObject<Document>();

src/JsonApiDotNetCore/Serialization/BaseSerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ protected string SerializeObject(object value, JsonSerializerSettings defaultSet
9999
{
100100
ArgumentGuard.NotNull(defaultSettings, nameof(defaultSettings));
101101

102-
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Serialize"))
102+
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Serialize", MeasurementConstants.ExcludeNewtonsoftJsonInPercentages))
103103
{
104104
var serializer = JsonSerializer.CreateDefault(defaultSettings);
105105
changeSerializer?.Invoke(serializer);

src/JsonApiDotNetCore/Serialization/RequestDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private object DeserializeOperationsDocument(string body)
7979
{
8080
AtomicOperationsDocument document;
8181

82-
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Deserialize"))
82+
using (CodeTimingSessionManager.Current.Measure("Newtonsoft.Deserialize", MeasurementConstants.ExcludeNewtonsoftJsonInPercentages))
8383
{
8484
JToken bodyToken = LoadJToken(body);
8585
document = bodyToken.ToObject<AtomicOperationsDocument>();

0 commit comments

Comments
 (0)