.NET Core中的性能测试工具BenchmarkDotnet

https://www.cnblogs.com/lwqlun/p/9671611.html

背景介绍

之前一篇博客中,我们讲解.NET Core中的CSV解析库,在文章的最后,作者使用了性能基准测试工具BenchmarkDotNet测试了2个不同CSV解析库的性能,本篇我们来详细介绍一下BenchmarkDotNet。

原文链接:https://dotnetcoretutorials.com/2017/12/04/benchmarking-net-core-code-benchmarkdotnet/

为什么需要性能基准测试?

性能基准测试可以帮助程序员对比2个代码段或者方法的性能,这对于代码重写或者重构来说,可以提供一种很好的量化标准。如果没有性能基准测试,很难想象将方法A改为B方法时候,仅凭肉眼如何区分性能的变化。

BenchmarkDotNet

BenchmarkDotNet是一款强力的.NET性能基准测试库, 官网https://benchmarkdotnet.org/。

运行时支持

NET Framework (4.6+),

.NET Core (2.0+)

Mono

CoreRT。

BenchmarkDotnet为每个被测试的方法提供了孤立的环境, 使用BenchmarkDotnet, 程序员可以很容易的编写各种性能测试方法,并可以避免许多常见的坑。

代码基准测试(Code Benchmarking)

现在我们希望来对比一下Linq to object中First和Single方法的性能

虽然我们知道First的性能肯定比Single高, First方法会在查询到第一个满足条件的对象之后就停止集合遍历,而Single找到第一个满足条件的对象之后,不会停止查找,它会去继续查找集合中的剩余对象,直到遍历整个集合或者在集合中找到第二个匹配条件的对象。 这里我们只是为了演示一下如何进行代码基准测试。

为了使用BenchmarkDotNet来进行代码基准测试,我们首先创建一个空的.Net Core控制台程序。

然后我们使用Package Manage Console添加BenchmarkDotNet库

PM> Install-Package BenchmarkDotNet

然后我们修改Program.cs文件, 代码如下

public class Program
{
public class SingleVsFirst
{
private readonly List<string> _haystack = new List<string>();
private readonly int _haystackSize = 1000000;
private readonly string _needle = "needle"; public SingleVsFirst()
{
//Add a large amount of items to our list.
Enumerable.Range(1, _haystackSize).ToList().ForEach(x => _haystack.Add(x.ToString()));
//Insert the needle right in the middle.
_haystack.Insert(_haystackSize / 2, _needle);
} [Benchmark]
public string Single() => _haystack.SingleOrDefault(x => x == _needle); [Benchmark]
public string First() => _haystack.FirstOrDefault(x => x == _needle); } public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<SingleVsFirst>();
Console.ReadLine();
}
}

代码解释说明

以上代码中SingleVsFirst类是一个测试类。

测试类中我们生成了一个拥有100万对象的字符串集合。

我们在集合的中间位置插入了一个测试字符串,字符串的内容是"needle"。

代码中的Single和First方法,分别调用了Linq to object的SingleOrDefault和FirstOrDefault方法来查询字符串集合中的"needle"字符串。

在Single和First方法上,我们加入[Benchmark]特性, 拥有该特性的方法会出现在最后的基准检测报告中。

注意:

测试的方法必须是公开的(public), 如果把public去掉,程序不会产生任何结果

在运行程序之前,还有一步关键的操作,测试的程序需要使用Release模式编译,并且不能附加任何调试器(Debugger)

最终结果

现在我们运行程序,程序产生的最终报告如下

Method Mean Error StdDev Median
Single 28.12 ms 0.9347 ms 2.697 ms 28.93 ms
First 13.30 ms 0.8394 ms 2.475 ms 14.48 ms

结果中的第一列Mean表明了2个方法处理的平均响应时间,First比Single快了一倍(这和我们测试字符串放置的位置有关系)。

带测试参数的基准测试(Input Benchmarking)

BenchmarkDotNet中我们还可以使用[ParamsSource]参数来指定测试的用例范围。

在上面的代码中,我们测试了匹配字符串在集合中间位置时,First和Single的效率对比,下面我们修改上面的代码,我们希望分别测试匹配字符串在集合头部,尾部以及中间位置时First和Single的效率对比。

using System;

using System.Collections.Generic;

using System.Linq;

using BenchmarkDotNet.Attributes;

using BenchmarkDotNet.Running;

namespace BenchmarkExample

{

public class SingleVsFirst

{

private readonly List _haystack = new List();

private readonly int _haystackSize = 1000000;

    public List<string> _needles => new List<string> { "StartNeedle", "MiddleNeedle", "EndNeedle" };

    public SingleVsFirst()
{
//Add a large amount of items to our list.
Enumerable.Range(1, _haystackSize).ToList().ForEach(x => _haystack.Add(x.ToString())); //One at the start.
_haystack.Insert(0, _needles[0]);
//One right in the middle.
_haystack.Insert(_haystackSize / 2, _needles[1]);
//One at the end.
_haystack.Insert(_haystack.Count - 1, _needles[2]);
} [ParamsSource(nameof(_needles))]
public string Needle { get; set; } [Benchmark]
public string Single() => _haystack.SingleOrDefault(x => x == Needle); [Benchmark]
public string First() => _haystack.FirstOrDefault(x => x == Needle); } class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<SingleVsFirst>();
Console.ReadLine();
}
}

}

代码解释说明

我们创建了测试的用例字符串集合_needles

在构造函数中,我们在字符串集合的头部,中部,尾部分别插入了3个字符串

我们添加了一个属性Needle, 表示当前测试的用例,在被测试Single和First方法中,我们使用属性Needle来匹配

在属性Needle上我们加上了参数来源特性[ParamsSource], 并设置参数来源是_needles

最终效果

现在我们运行程序,程序产生的最终报告如下

Method Needle Mean Error StdDev Median
Single EndNeedle 23,266,757.53 ns 432,206.593 ns 591,609.263 ns 23,236,343.07 ns
First EndNeedle 24,984,621.12 ns 494,223.345 ns 783,890.599 ns 24,936,945.21 ns
Single MiddleNeedle 21,379,814.14 ns 806,253.579 ns 2,377,256.870 ns 22,436,101.14 ns
First MiddleNeedle 11,984,519.09 ns 315,184.021 ns 924,380.173 ns 12,233,700.94 ns
Single StartNeedle 23,650,243.23 ns 599,968.173 ns 714,219.431 ns 23,555,402.19 ns
First StartNeedle 89.17 ns 1.864 ns 2.732 ns 89.07 ns

从结果上看

当匹配字符串在集合头部的时候,First性能比Single高的多

当匹配字符串在集合中部的时候,First性能是比Single的一倍

当匹配字符串在集合尾部的时候,First和比Single的性能差不多

加入内存测试

在.NET Core中的CSV解析库中,我们使用了以下代码

[MemoryDiagnoser]
public class CsvBenchmarking
{
[Benchmark(Baseline =true)]
public IEnumerable<Automobile> CSVHelper()
{
TextReader reader = new StreamReader("import.txt");
var csvReader = new CsvReader(reader);
var records = csvReader.GetRecords<Automobile>();
return records.ToList();
} [Benchmark]
public IEnumerable<Automobile> TinyCsvParser()
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ',');
var csvParser = new CsvParser<Automobile>(csvParserOptions, new CsvAutomobileMapping()); var records = csvParser.ReadFromFile("import.txt", Encoding.UTF8); return records.Select(x => x.Result).ToList();
}
}

其中除了[Benchmark]特性,我们还在测试类CsvBenchmarking上添加了[MemoryDiagnoser]特性,该特性会在测试报告中追加,2个方法执行时的内存使用情况。

    Method |       Mean | Scaled | Allocated |

-------------- |-----------

性能测试工具BenchmarkDotnet的更多相关文章

  1. .NET Core中的性能测试工具BenchmarkDotnet

    背景介绍 之前一篇博客中,我们讲解.NET Core中的CSV解析库,在文章的最后,作者使用了性能基准测试工具BenchmarkDotNet测试了2个不同CSV解析库的性能,本篇我们来详细介绍一下Be ...

  2. .NET平台性能测试工具BenchmarkDotnet 简介[译文]

    项目中需要用到性能测试,发现.net 平台的这个神器. 觉得很不错,接下来准备做个系列.具体参考官方介绍 做基线对比测试不是那么容易,你很容易就翻车掉坑里,BenchmarkDotNet 会帮你避坑( ...

  3. 性能测试工具 wrk 安装与使用

    介绍 今天给大家介绍一款开源的性能测试工具 wrk,简单易用,没有Load Runner那么复杂,他和 apache benchmark(ab)同属于性能测试工具,但是比 ab 功能更加强大,并且可以 ...

  4. .NET Core性能测试组件BenchmarkDotNet 支持.NET Framework Mono

    .NET Core 超强性能测试组件BenchmarkDotNet 支持Full .NET Framework, .NET Core (RTM), Mono. BenchmarkDotNet支持 C# ...

  5. 性能测试工具Locust

    An open source load testing tool. 一个开源性能测试工具. define user behaviour with python code, and swarm your ...

  6. 给CentOS6.3 + PHP5.3 安装PHP性能测试工具 XHProf-0.9.2

    一.什么是XHProf XHProf官网:http://pecl.php.net/package/xhprof XHProf是一个分层PHP性能分析工具.它报告函数级别的请求次数和各种指标,包括 阻塞 ...

  7. Android性能测试工具APT使用指南

    腾讯的安卓平台高效的性能测试工具APT(Android Performance Testing Tools),适用于开发自测和定位性能瓶颈,帮助测试人员完成性能基准测试.竞品测试. APT提供了CPU ...

  8. 安卓性能测试工具-GT,安测试

    GT: 是腾讯出品的一款APP的随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE,  Integrated  Debug&Test  Environment).利用GT,仅凭一部 ...

  9. TCP/UDP网络性能测试工具 - Netperf (zz) ..网络测试工具

    在构建或管理一个网络系统时,我们更多的是关心网络的可用性,即网络是否连通,而对于其整体的性能往往考虑不多. 除了netperf以外.       还有很多其它的网络性能测试工具.       如db, ...

随机推荐

  1. 如何计算android设备的屏幕物理尺寸

    https://segmentfault.com/q/1010000002794179 通过android提供的接口,我们可以获取到如下的信息:int densityDpi = mContext.ge ...

  2. Python编程-编码、变量、数据类型

    一.Python和其他语言对比 C语言最接近机器语言,因此运行效率是最高的,但需要编译. JAVA更适合企业应用. PHP适合WEB页面应用. PYTHON语言更加简洁,丰富的类库,使初学者更易实现应 ...

  3. linux中获取堆栈空间大小的方法

    #include   <stdio.h> #include   <stdlib.h> #include   <sys/time.h> #include   < ...

  4. nodejs往文件写入内容代码

    const fs = require("fs"); // fs.wirteFile有三个参数 // 1,第一个参数是要写入的文件路径 // 2,第二个参数是要写入得内容 // 3, ...

  5. JMeter学习(一)目录介绍

    JMeter也学了一阵子了,对于基本的操作已了解,再回过头来看看Jmeter的目录,本篇是对于它的目录进行一些简单的介绍. JMeter解压之后打开,根目录如下图: 1.bin:可执行文件目录 2.d ...

  6. VC数据类型

    不同编码格式下的字符串处理及相互转化: ◆ 大家在编程时经常遇到的数据类型:● Ansi:char.char * .const char *CHAR.(PCHAR.PSTR.LPSTR).LPCSTR ...

  7. C# 反射通过GetCustomAttributes方法,获得自定义特性

    http://blog.csdn.net/litao2/article/details/17633107 使用反射访问: 自定义属性的信息和对其进行操作的方法. 一.实例1 1.代码: 如:Syste ...

  8. getchar与scanf区别

    scanf可以一次按照设定的输入格式输入多个变量数据.如int d,float f,char str[20],scanf("%d%f%s",d,f,str); getchar()只 ...

  9. nova cell配置

    Configuration option = Default value Description [cells] call_timeout = 60 (IntOpt) Seconds to wait ...

  10. 【转载】JAVA中线程的两种实现方法-实现Runnable接口和继承Thread类

    转自: http://blog.csdn.net/sunguangran/article/details/6069317 非常感谢原作者,整理的这么详细. 在java中可有两种方式实现多线程,一种是继 ...