如何在 C# 应用程序中衡量方法的性能
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
本操作指南描述了如何对 C# 代码和所用库的代码中的公共类的公共方法进行精确的性能测量。
Unchase Fluent Performance Meter是一个开源的跨平台 .Net Standard 2.0 库,专为方法性能测量而设计。
该库可用于支持 .NET Standard 2.0 的.NET Core 和 .NET Framework 应用程序,并允许:
- 对你的代码和所用库的代码中公共类的公共方法进行精确的性能测量(并记录测量的确切开始时间和结束时间);
- 向测量结果添加自定义数据。例如,方法和结果的输入参数值、方法执行的上下文或关联ID,这些都可以用于关联方法性能的多个测量结果;
- 将方法性能测量拆分为多个步骤,并存储每个步骤的个人数据。此外,您可以设置最小执行时间,该时间将作为保存步骤测量结果的参考(如果某个步骤完成得更快,则不会保存)。
- 将代码的某些部分从性能测量中排除(例如,对某些方法的调用,这些方法的执行时间无需保存以进行测量);
- 添加自定义命令,保证在方法性能测量结束后立即执行(例如,对获得的结果进行后处理,如记录日志或将数据写入存储);
- 为方法性能测量上下文中执行的代码添加自定义异常处理程序(可用于所有测量,或单独用于每个测量);
- 设置缓存时间,用于存储方法的性能测量结果,缓存时间过后将删除这些结果;
- 将方法调用者的信息添加到测量结果中,可以通过IHttpContextAccessor或在代码中指定调用者来实现(例如,您可以指定调用该方法的外部服务的名称);
- 在测量结果中添加有关性能测量开始位置的信息(引用文件名和调用该方法的确切行号);
- 在流程自行完成之前中止该方法的性能测量。
通过该方法进行性能测量所获得的数据可用于分析应用程序(包括其各个部分:内部 - 本地代码和外部 - 所用库的代码)的性能,并以方便您的图形形式显示。
目录
- 方法的性能测量
- 方法性能测量
DiagnosticSource(v1.1.0) - 方法性能测量与
WatchingPerformanceAttribute属性(v2.0.0) - 衡量外部库方法的性能
- 添加自定义数据并将其拆分为多个步骤
- 不包括测量
- 添加自定义命令和操作
- 添加异常处理程序
- 设置缓存时间
- 添加有关呼叫者和呼叫地点来源的信息(并中止测量)
入门
要使用该库,请将NuGet 包安装到您的项目中:
使用 NuGet 包管理器手动安装:
Install-Package Unchase.FluentPerformanceMeter
使用 .NET CLI:
dotnet add package Unchase.FluentPerformanceMeter --version {version}
其中 {version} 是您要安装的软件包的版本。例如:
dotnet add package Unchase.FluentPerformanceMeter --version 1.0.0
使用示例
方法的性能测量
以下是一个简单的库使用示例(未进行任何配置和额外设置),旨在演示如何衡量Asp.Net Core 2.2 WebAPI应用程序中SimpleWatchingMethodStartController 中某个方法(Action)的性能。您可以使用扩展方法 来 实现此目的。PerformanceMeterController.WatchingMethod().Start().StartWatching()
自 v1.0.5 起,您也可以使用 方法名.WatchingMethod().Start(SimpleWatchingMethodStart)或 。.StartWatching(SimpleWatchingMethodStart)
/// <summary>
/// Test GET method with simple performance watching.
/// </summary>
[HttpGet("SimpleWatchingMethodStart")]
public ActionResult SimpleWatchingMethodStart()
{
// for C# 8 you can use:
//using var pm = PerformanceMeter<PerformanceMeterController>.StartWatching();
using (PerformanceMeter<PerformanceMeterController>.WatchingMethod().Start())
{
// put your code with some logic here
return Ok();
}
}
要获取控制器类公共方法的性能测量结果,PerformanceMeterController可以调用以下方法:
/// <summary>
/// Get methods performance info for this controller.
/// </summary>
/// <returns>Returns methods performance info.</returns>
[HttpGet("GetPerformanceInfo")]
[IgnoreMethodPerformance]
public ActionResult<IPerformanceInfo> GetPerformanceInfo()
{
return Ok(PerformanceMeter<PerformanceMeterController>.PerformanceInfo);
}
该属性的
IgnoreMethodPerformance目的是为了在衡量性能时不考虑被它标记的方法。
调用该方法后SimpleWatchingMethodStart,GetPerformanceInfo我们收到:
{
"methodCalls": [
{
"methodName": "SimpleWatchingMethodStart",
"elapsed": "00:00:00.0016350",
"caller": "unknown",
"startTime": "2019-12-06T10:27:27.3385385Z",
"endTime": "2019-12-06T10:27:27.3401735Z",
"customData": {},
"steps": []
}
],
"totalActivity": [
{
"methodName": "SimpleWatchingMethodStart",
"callsCount": 1
}
],
"currentActivity": [
{
"methodName": "SimpleWatchingMethodStart",
"callsCount": 0
}
],
"uptimeSince": "2019-12-06T10:27:27.3370183Z",
"className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController",
"methodNames": [
"SimpleWatchingMethodStart"
],
"customData": {},
"timerFrequency": 10000000
}
利用直接投资获取绩效衡量结果
从v2.1.0版本开始,可以使用 ASP.NET Core 应用程序内置的依赖注入 (DI) 来获取类的公共方法的性能测量结果。为此,请将 以下代码添加到:Startap.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
// adds a singleton service to the specified IPerformanceInfo<MeasurableController> with DI
services.AddSingleton(s => PerformanceMeter<MeasurableController>.PerformanceInfo);
// ... the same for another classes (controllers)
// ...
}
然后,使用依赖注入(DI),您可以获得结果,例如,如下所示:
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
private readonly IPerformanceInfo<PerformanceMeterController> _performanceInfo;
public PerformanceMeterController(IPerformanceInfo<PerformanceMeterController> performanceInfo)
{
_performanceInfo = performanceInfo;
}
// ...
/// <summary>
/// Get methods performance info for this controller.
/// </summary>
/// <returns>Returns methods performance info.</returns>
[HttpGet("GetPerformanceInfoV2")]
[IgnoreMethodPerformance]
public ActionResult<IPerformanceInfo> GetPerformanceInfoV2()
{
return Ok(_performanceInfo);
}
// ...
}
方法的性能测量与DiagnosticSource
从v1.1.0版本开始,可以使用 `getPerformance()`和 `getPerformance()` 特殊属性来测量AspNetCore MVC应用程序中方法的性能。为此,请将NuGet包添加到项目中,并将以下代码添加到 ` .htaccess` 文件中:DiagnosticSourceWatchingWithDiagnosticSourceAttributeUnchase.FluentPerformanceMeter.AspNetCore.MvcStartap.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
// allows to measure methods performance for class "MeasurableClass" and "MeasurableSecondClass"
services.AddPerformanceDiagnosticObserver<MeasurableClass>();
services.AddPerformanceDiagnosticObserver<MeasurableSecondClass>();
// ... the same for another classes
services.AddMvc();
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UsePerformanceDiagnosticObserver();
app.UseMvc();
}
然后使用属性标记WatchingWithDiagnosticSourceAttribute各个方法:
[HttpGet("SimpleWatchingMethodStart")]
[WatchingWithDiagnosticSource]
public ActionResult SimpleWatchingMethodStart()
{
return Ok();
}
或者全班同学:
[ApiController]
[Route("api/v1/[controller]")]
[Produces("application/json")]
[SwaggerTag("Unchase.PerformanceMeter Test WebAPI Controller")]
[WatchingWithDiagnosticSource]
public class PerformanceMeterController : ControllerBase
{
// measurable methods
}
从v1.2.0版本开始,可以使用特殊属性结合其他属性,在AspNetCore MVC应用程序中向自定义方法性能测量数据添加调用参数:AddMethodArgumentsToCustomDataAttributeWatchingWithDiagnosticSourceAttribute
[HttpPost("SimpleWatchingMethodStartWithArgs")]
[WatchingWithDiagnosticSource]
[AddMethodArgumentsToCustomData("actionArguments")]
public ActionResult SimpleWatchingMethodStartWithArgs(DTOArgument arg)
{
return Ok();
}
调用该方法后SimpleWatchingMethodStartWithArgs,GetPerformanceInfo我们收到:
{
"methodCalls": [
{
"methodName": "SimpleWatchingMethodStartWithArgs",
"elapsed": "00:00:00.0016350",
"caller": "unknown",
"startTime": "2019-12-06T10:27:27.3385385Z",
"endTime": "2019-12-06T10:27:27.3401735Z",
"customData": {
"actionArguments": {
"arg": {
"data": "<string_in_DTOArgument>"
}
}
},
"steps": []
}
],
"totalActivity": [
{
"methodName": "SimpleWatchingMethodStartWithArgs",
"callsCount": 1
}
],
"currentActivity": [
{
"methodName": "SimpleWatchingMethodStartWithArgs",
"callsCount": 0
}
],
"uptimeSince": "2019-12-06T10:27:27.3370183Z",
"className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController",
"methodNames": [
"SimpleWatchingMethodStartWithArgs"
],
"customData": {},
"timerFrequency": 10000000
}
方法的性能测量与WatchingPerformanceAttribute属性
从v2.0.0版本开始,可以使用特殊属性来测量AspNetCore MVCWatchingPerformanceAttribute应用程序中方法(操作)的性能,还可以配置控制器中的方法性能监视Startup.cs。为此,请将NuGet包添加Unchase.FluentPerformanceMeter.AspNetCore.Mvc到项目中,并将以下代码添加到Startap.cs:
public void ConfigureServices(IServiceCollection services)
{
// ...
// allows to measure methods performance for class "MeasurableController" with configuring options
services.AddPerformanceMeter<MeasurableController>(options =>
{
// ALL of this is optional. You can simply call .AddPerformanceMeter<MeasurableController>() for all defaults
// Defaults: In-Memory for 5 minutes, everything watched, every user can see
// excludes a method from performance watching
options.ExcludeMethod(nameof(MeasurableController.MeasurableAction));
// to control which requests are watched, use the Func<HttpRequest, bool> option:
options.ShouldWatching = request => request.HttpContext.User.IsInRole("Dev");
// allows to add custom data from custom attributes ("MethodCustomDataAttribute", "MethodCallerAttribute") to performance watching
options.AddCustomDataFromCustomAttributes = false;
// allows to use "IgnoreMethodPerformanceAttribute" for excluding from performance watching
options.UseIgnoreMethodPerformanceAttribute = false;
// allows to watch actions performance annotated with special attribute ("WatchingPerformanceAttribute")
options.WatchForAnnotatedWithAttributeOnly = false;
// excludes a path from being watched
options.IgnorePath("/some_path");
// allows to add route path to custom data (with "pm_path" key)
options.AddRoutePathToCustomData = false;
// set cache time for the watched performance results for the controller class
options.SetMethodCallsCacheTime(5);
// adds common custom data (anonymous class) to class performance information
options.AddCustomData("Custom anonymous class", new { Name = "Custom Name", Value = 1 });
// set default exception handler for the controller class
options.SetDefaultExceptionHandler((ex) => Debug.WriteLine(ex.Message));
});
// ... and for "MeasurableSecondController" (without configuring options)
services.AddPerformanceMeter<MeasurableSecondController>();
// ... the same for another controllers
services.AddMvc();
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseRouting();
app.UseEndpoints(c =>
{
c.MapControllers();
// use performance watching for concrete controller (for example, "MeasurableController")
app.UsePerformanceMeterFor<MeasurableController>();
// ... the same for another controllers
});
}
然后使用属性标记WatchingPerformanceAttribute各个方法:
[HttpGet("SimpleWatchingMethodStartWatchingPerformanceAttribute")]
[WatchingPerformance]
public ActionResult SimpleWatchingMethodStartWatchingPerformanceAttribute()
{
return Ok();
}
或者全班同学:
[ApiController]
[Route("api/v1/[controller]")]
[Produces("application/json")]
[SwaggerTag("Unchase.PerformanceMeter Test WebAPI Controller")]
[WatchingPerformance]
public class PerformanceMeterController : ControllerBase
{
// measurable methods (actions)
}
衡量外部库方法的性能
要衡量第三方库中公共类的公共方法的性能,您应该明确指定类本身及其方法的名称:
[HttpGet("GetThreadSleepPerformance")]
public ActionResult<string> GetThreadSleepPerformance()
{
using (PerformanceMeter<Thread>.WatchingMethod(nameof(Thread.Sleep)).Start())
{
Thread.Sleep(1000);
}
return Ok(PerformanceMeter<Thread>.PerformanceInfo.MethodCalls.FirstOrDefault(ta => ta.MethodName == nameof(Thread.Sleep))?.Elapsed);
}
执行该方法将返回:
"00:00:01.0033040"
您可以通过以下调用获取与调用此方法相关的性能信息:
/// <summary>
/// Get methods performance info for Thread class.
/// </summary>
/// <returns>Returns Thread methods performance info.</returns>
[HttpGet("GetThreadPerformanceInfo")]
[IgnoreMethodPerformance]
public ActionResult<IPerformanceInfo> GetThreadPerformanceInfo()
{
return Ok(PerformanceMeter<Thread>.PerformanceInfo);
}
调用此方法后,您将看到:
{
"methodCalls": [
{
"methodName": "Sleep",
"elapsed": "00:00:01.0033040",
"caller": "unknown",
"startTime": "2019-12-06T13:08:09.336624Z",
"endTime": "2019-12-06T13:08:10.339928Z",
"customData": {},
"steps": []
}
],
"totalActivity": [
{
"methodName": "Abort",
"callsCount": 0
},
...
],
"currentActivity": [
{
"methodName": "Abort",
"callsCount": 0
},
...
],
"uptimeSince": "2019-12-06T13:08:09.3357028Z",
"className": "System.Threading.Thread",
"methodNames": [
"Abort",
...
],
"customData": {},
"timerFrequency": 10000000
}
添加自定义数据并将其拆分为多个步骤
您可以为特定类的所有方法的性能指标添加自定义数据。我们以PerformanceMeterController控制器类的静态构造函数为例:
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
/// <summary>
/// Static constructor.
/// </summary>
static PerformanceMeterController()
{
// add common custom data (string) to class performance information
PerformanceMeter<PerformanceMeterController>.AddCustomData("Tag", "CustomTag");
// add common custom data (anonymous class) to class performance information
PerformanceMeter<PerformanceMeterController>.AddCustomData("Custom anonymous class", new { Name = "Custom Name", Value = 1 });
}
// ... actions
}
此外,您可以使用扩展方法 .WithSettingData.CustomData("<key>", <value>)(也可以通过特殊属性使用MethodCustomDataAttribute)为特定度量添加自定义数据,并使用扩展方法为该度量的每个步骤(使用扩展方法添加 .Step("<step_name>")) 添加自定义数据.AddCustomData("<key>", <value>):
/// <summary>
/// Test GET method with simple performance watching (with steps).
/// </summary>
[HttpGet("SimpleStartWatchingWithSteps")]
[MethodCustomData("Custom data from attribute", "Attr")]
public ActionResult SimpleStartWatchingWithSteps()
{
using (var pm = PerformanceMeter<PerformanceMeterController>
.WatchingMethod()
.WithSettingData
.CustomData("coins", 1)
.CustomData("Coins sets", new
{
Gold = "Many",
Silver = 5
})
.Start())
{
// put your code with some logic here
// add "Step 1"
using (pm.Step("Step 1"))
{
Thread.Sleep(1000);
}
// add "Step 2" with custom data
using (var pmStep = pm.Step("Step 2").AddCustomData("step2 custom data", "data!"))
{
// add "Step 3 in Step 2"
using (pm.Step("Step 3 in Step 2"))
{
Thread.Sleep(1000);
}
// add custom data to "Step 2"
pmStep.AddCustomData("step2 another custom data", "data2!");
// get and remove custom data from "Step 2"
var customData = pmStep.GetAndRemoveCustomData<string>("step2 custom data");
// get custom data from "Step 2" (without removing)
var anotherCustomData = pmStep.GetCustomData<string>("step2 another custom data");
// ...
}
}
}
因此,当GetPerformanceInfo调用该函数时,我们会得到:
{
"methodCalls": [
{
"methodName": "SimpleStartWatchingWithSteps",
"elapsed": "00:00:02.0083031",
"caller": "unknown",
"startTime": "2019-12-06T11:58:18.9006891Z",
"endTime": "2019-12-06T11:58:20.9089922Z",
"customData": {
"Coins sets": {
"gold": "Many",
"silver": 5
},
"coins": 1,
"Custom data from attribute": "Attr"
},
"steps": [
{
"stepName": "Step 1",
"elapsed": "00:00:01.0009758",
"startTime": "2019-12-06T11:58:18.9018272Z",
"endTime": "2019-12-06T11:58:19.902803Z",
"customData": {}
},
{
"stepName": "Step 3 in Step 2",
"elapsed": "00:00:01.0004549",
"startTime": "2019-12-06T11:58:19.9046523Z",
"endTime": "2019-12-06T11:58:20.9051072Z",
"customData": {}
},
{
"stepName": "Step 2",
"elapsed": "00:00:01.0029596",
"startTime": "2019-12-06T11:58:19.904534Z",
"endTime": "2019-12-06T11:58:20.9074936Z",
"customData": {
"step2 another custom data": "data2!"
}
}
]
}
],
"totalActivity": [
{
"methodName": "SimpleStartWatchingWithSteps",
"callsCount": 1
}
],
"currentActivity": [
{
"methodName": "SimpleStartWatchingWithSteps",
"callsCount": 0
}
],
"uptimeSince": "2019-12-06T11:58:18.8801249Z",
"className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController",
"methodNames": [
"SimpleStartWatchingWithSteps"
],
"customData": {
"Tag": "CustomTag",
"Custom anonymous class": {
"name": "Custom Name",
"value": 1
}
},
"timerFrequency": 10000000
}
不包括测量
您可以排除方法性能测量的各个部分(使用 .Ignore()扩展 .Executing().WithoutWatching().Start(<Action>)方法),也可以跳过保存各个步骤(使用 .StepIf("<step_name>", <minSaveMs>)扩展方法),如果它们不满足条件(步骤执行时间将计入方法执行时间):
using (var pm = PerformanceMeter<PerformanceMeterController>.WatchingMethod().Start())
{
// put your code with some logic here
// sleep 1 sec
Thread.Sleep(1000);
// ignore this block in performance watching
using (pm.Ignore())
{
Thread.Sleep(5000);
}
// skip this step with minSaveMs (do not save the step results, but take into account its duration)
using (pm.StepIf("Skipped step", minSaveMs: 1000))
{
Thread.Sleep(500);
}
// execute action without performance watching
pm.Executing().WithoutWatching().Start(() =>
{
Thread.Sleep(2000);
});
return Ok();
}
因此,我们得到:
{
"methodCalls": [
{
"methodName": "SimpleStartWatchingWithIgnored",
"elapsed": "00:00:01.5080227",
"caller": "unknown",
"startTime": "2019-12-06T12:34:36.9187359Z",
"endTime": "2019-12-06T12:34:38.4267586Z",
"customData": {},
"steps": []
}
],
"totalActivity": [
{
"methodName": "SimpleStartWatchingWithIgnored",
"callsCount": 1
}
],
"currentActivity": [
{
"methodName": "SimpleStartWatchingWithIgnored",
"callsCount": 0
}
],
"uptimeSince": "2019-12-06T12:34:36.9035129Z",
"className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController",
"methodNames": [
"SimpleStartWatchingWithIgnored"
],
"customData": { },
"timerFrequency": 10000000
}
添加自定义命令和操作
要添加一个自定义命令,确保它在方法性能测量完成后执行,需要创建一个实现IPerformanceCommand相应接口的命令类。在这种情况下,您可以通过所创建命令的构造函数传递任意数据,这些数据将在命令执行时使用。例如:
/// <summary>
/// Custom executed command.
/// </summary>
public class ExecutedCommand : IPerformanceCommand
{
/// <summary>
/// Executed commad name.
/// </summary>
public string CommandName => this.GetType().Name;
private string _customString { get; }
internal bool IsCommandExecuted { get; private set; }
/// <summary>
/// Constructor.
/// </summary>
/// <remarks>
/// You can pass any data through the command constructor.
/// </remarks>
/// <param name="customString"></param>
public ExecutedCommand(string customString)
{
this._customString = customString;
}
/// <summary>
/// Execute command.
/// </summary>
/// <param name="performanceInfo"><see cref="IPerformanceInfo"/>.</param>
public void Execute(IPerformanceInfo performanceInfo)
{
// for example, write to the debug console some information
Debug.WriteLine(this.CommandName);
Debug.WriteLine(this._customString);
Debug.WriteLine($"Method names count: {performanceInfo.MethodNames.Count}");
this.IsCommandExecuted = true;
}
}
您可以添加自定义命令(IPerformanceCommand)和操作,以便在测量结束时按以下方式执行它们:
// custom "ExecutedCommand" will be executed after performance watching is completed
using (PerformanceMeter<PerformanceMeterController>
.WatchingMethod()
.WithExecutingOnComplete
.Command(new ExecutedCommand("bla-bla-bla"))
.Action((pi) =>
{
Debug.WriteLine($"Class name: {pi.ClassName}");
})
.Start())
{
return Ok();
}
因此,测量结束后,调试控制台将显示:
ExecutedCommand
bla-bla-bla
Method names count: 13
Class name: Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController
添加异常处理程序
如果需要处理在执行性能测量方法的某个部分时可能发生的异常,则需要按如下方式添加异常处理程序:
using (var pm = PerformanceMeter<PerformanceMeterController>.StartWatching())
{
// execute an action that throws the exception to be handled by the exception handler
pm.Executing()
.WithExceptionHandler((ex) => Debug.WriteLine(ex.Message))
.Start(() => throw new Exception("Exception"));
// execute action throws custom Exception with exception handler
pm.Executing<CustomException>()
.WithExceptionHandler((ex) => { Debug.WriteLine(ex.Message); })
.Start(() =>
{
throw new CustomException("Custom exception was occured!");
});
return Ok();
}
类位于何处CustomException(例如):
/// <summary>
/// Custom exception.
/// </summary>
public class CustomException : Exception
{
public CustomException(string message) : base(message) { }
public CustomException(string message, Exception innerException) : base(message, innerException) { }
public CustomException() { }
}
因此,调试控制台中将显示以下内容:
Exception
Custom exception was occured!
此外,您还可以指定一个异常处理程序,该程序将默认用于衡量给定类的任何方法的性能,例如,通过PerformanceMeterController控制器类的静态构造函数:
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
/// <summary>
/// Static constructor.
/// </summary>
static PerformanceMeterController()
{
// set default exception handler for PerformanceMeterController class
PerformanceMeter<PerformanceMeterController>.SetDefaultExceptionHandler((ex) => Debug.WriteLine(ex.Message));
}
// ... actions
}
设置缓存时间
您可以设置缓存时间,用于存储方法性能测量结果,之后这些结果将被删除。每个待测量的类都需要单独设置此时间。例如,可以通过PerformanceMeterController控制器类的静态构造函数设置此时间:
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
/// <summary>
/// Static constructor.
/// </summary>
static PerformanceMeterController()
{
// set cache time for PerformanceMeterController class
PerformanceMeter<PerformanceMeterController>.SetMethodCallsCacheTime(5);
}
// ... actions
}
添加有关呼叫者和呼叫地点来源的信息(并中止测量)
.CallerFrom("<caller_name>")您可以使用扩展方法(可以传递字符串值或IHttpContextAccessor对象)或方法的特殊属性来指定方法的调用者[MethodCaller ("<caller_name>")]。此外,如果同时使用属性和扩展方法,则值将取自后者。- 要为性能测量添加调用源,请使用扩展方法
.WithSettingData.CallerSourceData()。 - 要在using代码块内停止/中止性能测量,请使用
.StopWatching()扩展方法或Dispose()直接使用该方法:
[HttpPost("StartWatchingWithCallerName")]
[MethodCaller("testCaller")]
public ActionResult<string> StartWatchingWithCallerName([FromBody] string value)
{
// the method's performance info will be amended with the caller's name (if internal HttpContextAccessor is null)
using (var pm = PerformanceMeter<PerformanceMeterController>
.WatchingMethod()
.WithSettingData
.CallerSourceData()
.CallerFrom("Test caller")
.Start())
{
pm.StopWatching(); // stop watching here (or you can use "pm.Dispose();")
Thread.Sleep(2000);
return Ok(value);
}
}
调用该方法后GetPerformanceInfo,您将得到:
{
"methodCalls": [
{
"methodName": "StartWatchingWithCallerName",
"elapsed": "00:00:00.0019172",
"caller": "Test caller",
"startTime": "2019-12-06T13:35:45.3164507Z",
"endTime": "2019-12-06T13:35:45.3183679Z",
"customData": {
"customData123": 123,
"callerSourceLineNumber": 525,
"callerSource": "D:\\GitHub\\Unchase.FluentPerformanceMeter\\Unchase.FluentPerformanceMeter.TestWebAPI\\Controllers\\PerformanceMeterController.cs"
},
"steps": []
}
],
"totalActivity": [
{
"methodName": "StartWatchingWithCallerName",
"callsCount": 1
}
],
"currentActivity": [
{
"methodName": "StartWatchingWithCallerName",
"callsCount": 0
}
],
"uptimeSince": "2019-12-06T13:35:45.2601668Z",
"className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController",
"methodNames": [
"StartWatchingWithCallerName"
],
"customData": { },
"timerFrequency": 10000000
}
使用Unchase享受编程的乐趣!
文章来源:https://dev.to/unchase/how-to-measure-a-method-s-performance-in-c-applications-3jji