Reduce allocations when Activity is enabled (#11020)
- Remove string allocations caused by DiagnosticSource.Stop/StartActivity - Pass the HttpContext directly as the object for StartActivity and StopActivity to avoid the anonymous object allocation. - Though it's a bit ugly, added an HttpContext property to DefaultHttpContext to avoid breaking back-compat (which had to do reflection to get the HttpContext property anyways)
This commit is contained in:
parent
c89055b9b0
commit
d4a982fefa
|
|
@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
private static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
|
private static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
|
||||||
|
|
||||||
private const string ActivityName = "Microsoft.AspNetCore.Hosting.HttpRequestIn";
|
private const string ActivityName = "Microsoft.AspNetCore.Hosting.HttpRequestIn";
|
||||||
private const string ActivityStartKey = "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start";
|
private const string ActivityStartKey = ActivityName + ".Start";
|
||||||
|
private const string ActivityStopKey = ActivityName + ".Stop";
|
||||||
|
|
||||||
private const string DeprecatedDiagnosticsBeginRequestKey = "Microsoft.AspNetCore.Hosting.BeginRequest";
|
private const string DeprecatedDiagnosticsBeginRequestKey = "Microsoft.AspNetCore.Hosting.BeginRequest";
|
||||||
private const string DeprecatedDiagnosticsEndRequestKey = "Microsoft.AspNetCore.Hosting.EndRequest";
|
private const string DeprecatedDiagnosticsEndRequestKey = "Microsoft.AspNetCore.Hosting.EndRequest";
|
||||||
|
|
@ -278,7 +279,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
if (_diagnosticListener.IsEnabled(ActivityStartKey))
|
if (_diagnosticListener.IsEnabled(ActivityStartKey))
|
||||||
{
|
{
|
||||||
hasDiagnosticListener = true;
|
hasDiagnosticListener = true;
|
||||||
_diagnosticListener.StartActivity(activity, new { HttpContext = httpContext });
|
StartActivity(activity, httpContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -293,12 +294,32 @@ namespace Microsoft.AspNetCore.Hosting.Internal
|
||||||
{
|
{
|
||||||
if (hasDiagnosticListener)
|
if (hasDiagnosticListener)
|
||||||
{
|
{
|
||||||
_diagnosticListener.StopActivity(activity, new { HttpContext = httpContext });
|
StopActivity(activity, httpContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
activity.Stop();
|
activity.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are versions of DiagnosticSource.Start/StopActivity that don't allocate strings per call (see https://github.com/dotnet/corefx/issues/37055)
|
||||||
|
private Activity StartActivity(Activity activity, HttpContext httpContext)
|
||||||
|
{
|
||||||
|
activity.Start();
|
||||||
|
_diagnosticListener.Write(ActivityStartKey, httpContext);
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopActivity(Activity activity, HttpContext httpContext)
|
||||||
|
{
|
||||||
|
// Stop sets the end time if it was unset, but we want it set before we issue the write
|
||||||
|
// so we do it now.
|
||||||
|
if (activity.Duration == TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
activity.SetEndTime(DateTime.UtcNow);
|
||||||
|
}
|
||||||
|
_diagnosticListener.Write(ActivityStopKey, httpContext);
|
||||||
|
activity.Stop(); // Resets Activity.Current (we want this after the Write)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ namespace Microsoft.AspNetCore.Http
|
||||||
public override Microsoft.AspNetCore.Http.ConnectionInfo Connection { get { throw null; } }
|
public override Microsoft.AspNetCore.Http.ConnectionInfo Connection { get { throw null; } }
|
||||||
public override Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get { throw null; } }
|
public override Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get { throw null; } }
|
||||||
public Microsoft.AspNetCore.Http.Features.FormOptions FormOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
public Microsoft.AspNetCore.Http.Features.FormOptions FormOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||||
|
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
public Microsoft.AspNetCore.Http.HttpContext HttpContext { get { throw null; } }
|
||||||
public override System.Collections.Generic.IDictionary<object, object> Items { get { throw null; } set { } }
|
public override System.Collections.Generic.IDictionary<object, object> Items { get { throw null; } set { } }
|
||||||
public override Microsoft.AspNetCore.Http.HttpRequest Request { get { throw null; } }
|
public override Microsoft.AspNetCore.Http.HttpRequest Request { get { throw null; } }
|
||||||
public override System.Threading.CancellationToken RequestAborted { get { throw null; } set { } }
|
public override System.Threading.CancellationToken RequestAborted { get { throw null; } set { } }
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
|
@ -157,6 +158,12 @@ namespace Microsoft.AspNetCore.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This property exists because of backwards compatibility.
|
||||||
|
// We send an anonymous object with an HttpContext property
|
||||||
|
// via DiagnosticSource in various events throughout the pipeline. Instead
|
||||||
|
// we just send the HttpContext to avoid extra allocations
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public HttpContext HttpContext => this;
|
||||||
|
|
||||||
public override void Abort()
|
public override void Abort()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue