发布于 2026-01-06 0 阅读
0

如何衡量 C# 应用程序中方法的性能?DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

如何在 C# 应用程序中衡量方法的性能

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

本操作指南描述了如何对 C# 代码和所用库的代码中的公共类的公共方法进行精确的性能测量。

Unchase Fluent Performance Meter是一个开源的跨平台 .Net Standard 2.0 库,专为方法性能测量而设计。

该库可用于支持 .NET Standard 2.0 的.NET Core 和 .NET Framework 应用程序,并允许:

通过该方法进行性能测量所获得的数据可用于分析应用程序(包括其各个部分:内部 - 本地代码和外部 - 所用库的代码)的性能,并以方便您的图形形式显示。


目录

  1. 入门
  2. 使用示例

入门

要使用该库,请将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目的是为了在衡量性能时不考虑被它标记的方法。

调用该方法后SimpleWatchingMethodStartGetPerformanceInfo我们收到:

{
  "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();
}

调用该方法后SimpleWatchingMethodStartWithArgsGetPerformanceInfo我们收到:

{
  "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