热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:BenchmarkDotNet性能测试

篇首语:本文由编程笔记#小编为大家整理,主要介绍了BenchmarkDotNet性能测试相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了BenchmarkDotNet性能测试相关的知识,希望对你有一定的参考价值。








BenchmarkDotNet是一款开源的性能测试工具,使用方式非常简单,特别是对实现同一功能的两种方式,犹豫不决时,可以使用它进行个对比。


比如我们比较ADO.NET方式查询数据库表,和用Dapper方式获取数据为表,只需要在两个方法上增加 [Benchmark]就可以了,然后调用var summary = BenchmarkRunner.Run();就实现了性能测试。


using System;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Security.Cryptography;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using Dapper;
namespace MyBenchmarks
{
public class Product
{
public string Name { get; set; }
public string ProductNumber { get; set; }
public bool MakeFlag { get; set; }
public bool FinishedGoodsFlag { get; set; }
public string Color { get; set; }
public short SafetyStockLevel { get; set; }
public short ReorderPoint { get; set; }
public decimal StandardCost { get; set; }
public decimal ListPrice { get; set; }
public string Size { get; set; }
public string SizeUnitMeasureCode { get; set; }
public string WeightUnitMeasureCode { get; set; }
public double Weight { get; set; }
public int DaysToManufacture { get; set; }
public string ProductLine { get; set; }
public string Class { get; set; }
public string Style { get; set; }
public int ProductSubcategoryID { get; set; }
public int ProductModelID { get; set; }
public DateTime SellStartDate { get; set; }
public DateTime SellEndDate { get; set; }
public DateTime DiscontinuedDate { get; set; }
public Guid rowguid { get; set; }
public DateTime ModifiedDate { get; set; }

}
public class Cycle
{
[Benchmark]
public void DapperTest()
{
var conn = new SqlConnection("Data Source=.;Initial Catalog=AdventureWorks2016;Persist Security Info=True;User ID=sa;password=sa;");
var table = conn.Query("select top 100 * from production.product");
}
[Benchmark]
public void CommandTest()
{
var conn = "Data Source=.;Initial Catalog=AdventureWorks2016;Persist Security Info=True;User ID=sa;password=sa;";
var sql = "select top 100 * from production.product";
var dapp = new SqlDataAdapter(sql, conn);
var table = new DataTable();
dapp.Fill(table);
}
}
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run();
}
}
}

运行一下看一下结果,为了减少篇幅,删除了一些结果,从结果看出,为了得到较为客观的性能测试结果,BenchmarkDotNet还是做了很多工作的:


OverheadJitting,WorkloadJitting,WorkloadPilot,OverheadWarmup,OverheadActual,WorkloadWarmup,WorkloadActual,WorkloadResult。


并且通过最后的一个表格,清楚的给出了结果。同时还给出了Warnings ,以供参考。


// Validating benchmarks:
// ***** BenchmarkRunner: Start *****
// ***** Found 2 benchmark(s) in total *****
// ***** Building 1 exe(s) in Parallel: Start *****
// start dotnet restore /p:UseSharedCompilation=false /p:BuildInParallel=false /m:1 /p:Deterministic=true /p:Optimize=true in C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\BenchmarkDotNet\\Demo01\\bin\\Release\\net6.0\\03bf0209-ac26-4de1-b763-4ba03e46cf4d
// command took 2.83s and exited with 0
// start dotnet build -c Release --no-restore /p:UseSharedCompilation=false /p:BuildInParallel=false /m:1 /p:Deterministic=true /p:Optimize=true in C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\BenchmarkDotNet\\Demo01\\bin\\Release\\net6.0\\03bf0209-ac26-4de1-b763-4ba03e46cf4d
// command took 4.29s and exited with 0
// ***** Done, took 00:00:07 (7.52 sec) *****
// Found 2 benchmarks:
// Cycle.DapperTest: DefaultJob
// Cycle.CommandTest: DefaultJob
// **************************
// Benchmark: Cycle.DapperTest: DefaultJob
// *** Execute ***
// Launch: 1 / 1
// Execute: dotnet "03bf0209-ac26-4de1-b763-4ba03e46cf4d.dll" --benchmarkName "MyBenchmarks.Cycle.DapperTest" --job "Default" --benchmarkId 0 in C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\BenchmarkDotNet\\Demo01\\bin\\Release\\net6.0\\03bf0209-ac26-4de1-b763-4ba03e46cf4d\\bin\\Release\\net6.0
// BeforeAnythingElse
// Benchmark Process Environment Information:
// Runtime=.NET 6.0.0 (6.0.21.25307), X64 RyuJIT
// GC=Concurrent Workstation
// Job: DefaultJob
OverheadJitting 1: 1 op, 229700.00 ns, 229.7000 us/op
WorkloadJitting 1: 1 op, 410021000.00 ns, 410.0210 ms/op
WorkloadWarmup 1: 1 op, 4581600.00 ns, 4.5816 ms/op
WorkloadWarmup 2: 1 op, 746500.00 ns, 746.5000 us/op
WorkloadWarmup 3: 1 op, 830000.00 ns, 830.0000 us/op
WorkloadWarmup 4: 1 op, 822900.00 ns, 822.9000 us/op
WorkloadWarmup 5: 1 op, 741800.00 ns, 741.8000 us/op
WorkloadWarmup 6: 1 op, 746900.00 ns, 746.9000 us/op
WorkloadWarmup 7: 1 op, 826300.00 ns, 826.3000 us/op
WorkloadWarmup 8: 1 op, 698300.00 ns, 698.3000 us/op
// BeforeActualRun
WorkloadActual 1: 1 op, 755100.00 ns, 755.1000 us/op
……
WorkloadActual 100: 1 op, 712700.00 ns, 712.7000 us/op
// AfterActualRun
WorkloadResult 1: 1 op, 755100.00 ns, 755.1000 us/op
……
WorkloadResult 95: 1 op, 712700.00 ns, 712.7000 us/op
// AfterAll
// Benchmark Process 26724 has exited with code 0
Mean = 753.054 us, StdErr = 11.687 us (1.55%), N = 95, StdDev = 113.909 us
Min = 578.400 us, Q1 = 668.600 us, Median = 734.900 us, Q3 = 798.800 us, Max = 1,052.600 us
IQR = 130.200 us, LowerFence = 473.300 us, UpperFence = 994.100 us
ConfidenceInterval = [713.353 us; 792.754 us] (CI 99.9%), Margin = 39.701 us (5.27% of Mean)
Skewness = 0.87, Kurtosis = 2.93, MValue = 3.63
// **************************
// Benchmark: Cycle.CommandTest: DefaultJob
// *** Execute ***
// Launch: 1 / 1
// Execute: dotnet "03bf0209-ac26-4de1-b763-4ba03e46cf4d.dll" --benchmarkName "MyBenchmarks.Cycle.CommandTest" --job "Default" --benchmarkId 1 in C:\\MyFile\\Source\\Repos\\Asp.NetCoreExperiment\\Asp.NetCoreExperiment\\BenchmarkDotNet\\Demo01\\bin\\Release\\net6.0\\03bf0209-ac26-4de1-b763-4ba03e46cf4d\\bin\\Release\\net6.0
// BeforeAnythingElse
// Benchmark Process Environment Information:
// Runtime=.NET 6.0.0 (6.0.21.25307), X64 RyuJIT
// GC=Concurrent Workstation
// Job: DefaultJob
OverheadJitting 1: 1 op, 215400.00 ns, 215.4000 us/op
WorkloadJitting 1: 1 op, 339247500.00 ns, 339.2475 ms/op
WorkloadWarmup 1: 1 op, 3680100.00 ns, 3.6801 ms/op
WorkloadWarmup 2: 1 op, 943000.00 ns, 943.0000 us/op
WorkloadWarmup 3: 1 op, 875200.00 ns, 875.2000 us/op
WorkloadWarmup 4: 1 op, 982500.00 ns, 982.5000 us/op
WorkloadWarmup 5: 1 op, 956900.00 ns, 956.9000 us/op
WorkloadWarmup 6: 1 op, 1030800.00 ns, 1.0308 ms/op
WorkloadWarmup 7: 1 op, 1170900.00 ns, 1.1709 ms/op
WorkloadWarmup 8: 1 op, 1169400.00 ns, 1.1694 ms/op
// BeforeActualRun
WorkloadActual 1: 1 op, 975400.00 ns, 975.4000 us/op
……
WorkloadActual 100: 1 op, 897400.00 ns, 897.4000 us/op
// AfterActualRun
WorkloadResult 1: 1 op, 975400.00 ns, 975.4000 us/op
……
WorkloadResult 91: 1 op, 897400.00 ns, 897.4000 us/op
// AfterAll
// Benchmark Process 17300 has exited with code 0
Mean = 951.263 us, StdErr = 13.676 us (1.44%), N = 91, StdDev = 130.465 us
Min = 759.300 us, Q1 = 864.000 us, Median = 912.900 us, Q3 = 1,004.600 us, Max = 1,316.000 us
IQR = 140.600 us, LowerFence = 653.100 us, UpperFence = 1,215.500 us
ConfidenceInterval = [904.736 us; 997.789 us] (CI 99.9%), Margin = 46.526 us (4.89% of Mean)
Skewness = 0.95, Kurtosis = 3.05, MValue = 2.44
// ***** BenchmarkRunner: Finish *****
// * Export *
BenchmarkDotNet.Artifacts\\results\\MyBenchmarks.Cycle-report.csv
BenchmarkDotNet.Artifacts\\results\\MyBenchmarks.Cycle-report-github.md
BenchmarkDotNet.Artifacts\\results\\MyBenchmarks.Cycle-report.html
// * Detailed results *
Cycle.DapperTest: DefaultJob
Runtime = .NET 6.0.0 (6.0.21.25307), X64 RyuJIT; GC = Concurrent Workstation
Mean = 753.054 us, StdErr = 11.687 us (1.55%), N = 95, StdDev = 113.909 us
Min = 578.400 us, Q1 = 668.600 us, Median = 734.900 us, Q3 = 798.800 us, Max = 1,052.600 us
IQR = 130.200 us, LowerFence = 473.300 us, UpperFence = 994.100 us
ConfidenceInterval = [713.353 us; 792.754 us] (CI 99.9%), Margin = 39.701 us (5.27% of Mean)
Skewness = 0.87, Kurtosis = 2.93, MValue = 3.63
-------------------- Histogram --------------------
[ 545.635 us ; 582.035 us) | @
[ 582.035 us ; 650.935 us) | @@@@@@@@@@@@@@@
[ 650.935 us ; 726.135 us) | @@@@@@@@@@@@@@@@@@@@@@@@@@@
[ 726.135 us ; 791.665 us) | @@@@@@@@@@@@@@@@@@@@@@@@@@@@
[ 791.665 us ; 852.365 us) | @@@@@@@@
[ 852.365 us ; 924.365 us) | @@@
[ 924.365 us ; 1,009.685 us) | @@@@@@@@@@@
[1,009.685 us ; 1,085.365 us) | @@
---------------------------------------------------
Cycle.CommandTest: DefaultJob
Runtime = .NET 6.0.0 (6.0.21.25307), X64 RyuJIT; GC = Concurrent Workstation
Mean = 951.263 us, StdErr = 13.676 us (1.44%), N = 91, StdDev = 130.465 us
Min = 759.300 us, Q1 = 864.000 us, Median = 912.900 us, Q3 = 1,004.600 us, Max = 1,316.000 us
IQR = 140.600 us, LowerFence = 653.100 us, UpperFence = 1,215.500 us
ConfidenceInterval = [904.736 us; 997.789 us] (CI 99.9%), Margin = 46.526 us (4.89% of Mean)
Skewness = 0.95, Kurtosis = 3.05, MValue = 2.44
-------------------- Histogram --------------------
[ 721.230 us ; 780.280 us) | @@
[ 780.280 us ; 860.730 us) | @@@@@@@@@@@@@@@@@@@@
[ 860.730 us ; 936.870 us) | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
[ 936.870 us ; 1,020.120 us) | @@@@@@@@@@@@@@@@
[1,020.120 us ; 1,080.630 us) | @@@@@
[1,080.630 us ; 1,170.980 us) | @@@@@@@
[1,170.980 us ; 1,247.120 us) | @@@@@@@@
[1,247.120 us ; 1,277.930 us) |
[1,277.930 us ; 1,354.070 us) | @
---------------------------------------------------
// * Summary *
BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19043.1052 (21H1/May2021Update)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET SDK=6.0.100-preview.4.21255.9
[Host] : .NET 6.0.0 (6.0.21.25307), X64 RyuJIT [AttachedDebugger]
DefaultJob : .NET 6.0.0 (6.0.21.25307), X64 RyuJIT

| Method | Mean | Error | StdDev | Median |
|------------ |---------:|---------:|---------:|---------:|
| DapperTest | 753.1 us | 39.70 us | 113.9 us | 734.9 us |
| CommandTest | 951.3 us | 46.53 us | 130.5 us | 912.9 us |
// * Warnings *
MultimodalDistribution
Cycle.DapperTest: Default -> It seems that the distribution is bimodal (mValue = 3.63)
Environment
Summary -> Benchmark was executed with attached debugger
MinIterationTime
Cycle.DapperTest: Default -> The minimum observed iteration time is 578.4000 us which is very small. It's recommended to increase it to at least 100.0000 ms using more operations.
Cycle.CommandTest: Default -> The minimum observed iteration time is 759.3000 us which is very small. It's recommended to increase it to at least 100.0000 ms using more operations.
// * Hints *
Outliers
Cycle.DapperTest: Default -> 5 outliers were removed (1.06 ms..2.17 ms)
Cycle.CommandTest: Default -> 9 outliers were removed (1.37 ms..2.51 ms)
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
1 us : 1 Microsecond (0.000001 sec)
// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:00:03 (3.12 sec), executed benchmarks: 2
Global total time: 00:00:10 (10.65 sec), executed benchmarks: 2
// * Artifacts cleanup *




推荐阅读
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了如何将CIM_DateTime解析为.Net DateTime,并分享了解析过程中可能遇到的问题和解决方法。通过使用DateTime.ParseExact方法和适当的格式字符串,可以成功解析CIM_DateTime字符串。同时还提供了关于WMI和字符串格式的相关信息。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
author-avatar
彭元蓮_198
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有