再看.Net 官方博客 <<.Net 5性能優化>> 中,發現測試性能的Benchmarkdotnet版本已經是v0.12.1,然後去看BenchmarkDotNet文檔,發現還是有不少新的特性.
v0.12.0
v0.12.1
<!--新增.Net 5運行時-->
<TargetFrameworks>net5.0;netcoreapp3.1;net48</TargetFrameworks>
//以.NetFramework 4.8為基準,測試三個版本 .NetFramework 4.8/.Net Core 3.1和.Net 5
dotnet run -c Release -f net48 --runtimes net48 netcoreapp31 netcoreapp50 --filter ** --join
先查看.Net 5下,有什麼項目模闆(不是必需,可以自己新建項目引用BenchmarkDotNet):
//查看.Net有哪些項目模闆
dotnet new -l
.Net 5自帶的項目模版
通過命令安裝模闆:
// -i 代表install
dotnet new -i BenchmarkDotNet.Templates
在.Net 5中安裝BenchmarkDotNet的項目模闆
通過命令卸載安裝過的模闆:
//-u 代表卸載 u為uninsall
dotnet new -u BenchmarkDotNet.Templates
在.Net 5中卸載BenchmarkDotNet項目模闆
新建Benchmark項目:
//新建BenchmarkDotNet項目
dotnet new benchmark --console-app
在.Net 5中通過BenchmarkDotNet項目模闆新建項目Benchmark項目
NativeMemoryProfiler使用在Nuget管理器中安裝BenchmarkDotNet.Diagnostics.Windows包.
在Nuget管理器中安裝BenchmarkDotNet.Diagnostics.Windows
執行後生成的結果(沒有執行完成,是因為電腦在運行的時候突然藍屏,懷疑是CPU溫度過高造成的,因為筆記本好幾年沒有換過散熱矽脂了):
BenchmarkDotNet 執行生成的結果
看BenchmarkDotNet文檔中代碼:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows.Configs;
namespace dotnet_perf
{
[DisassemblyDiagnoser]
[NativeMemoryProfiler] //在BenchmarkDotNet.Diagnostics.Windows.Configs命名空間下
[MemoryDiagnoser]
public class IntroNativeMemory
{
[Benchmark]
public void BitmapWithLeaks()
{
var flag = new Bitmap(200, 100);
var graphics = Graphics.FromImage(flag);
var blackPen = new Pen(Color.Black, 3);
graphics.DrawLine(blackPen, 100, 100, 500, 100);
}
[Benchmark]
public void Bitmap()
{
using (var flag = new Bitmap(200, 100))
{
using (var graphics = Graphics.FromImage(flag))
{
using (var blackPen = new Pen(Color.Black, 3))
{
graphics.DrawLine(blackPen, 100, 100, 500, 100);
}
}
}
}
private const int Size = 20; // Greater value could cause System.OutOfMemoryException for test with memory leaks.
private int ArraySize = Size * Marshal.SizeOf(typeof(int));
[Benchmark]
public unsafe void AllocHGlobal()
{
IntPtr unmanagedHandle = Marshal.AllocHGlobal(ArraySize);
Span<byte> unmanaged = new Span<byte>(unmanagedHandle.ToPointer(), ArraySize);
Marshal.FreeHGlobal(unmanagedHandle);
}
[Benchmark]
public unsafe void AllocHGlobalWithLeaks()
{
IntPtr unmanagedHandle = Marshal.AllocHGlobal(ArraySize);
Span<byte> unmanaged = new Span<byte>(unmanagedHandle.ToPointer(), ArraySize);
}
}
}
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
namespace dotnet_perf
{
[ThreadingDiagnoser] //在BenchmarkDotNet.Diagnosers命名空間下
public class IntroThreadingDiagnoser
{
[Benchmark]
public void CompleteOneWorkItem()
{
ManualResetEvent done = new ManualResetEvent(initialState: false);
ThreadPool.QueueUserWorkItem(m => (m as ManualResetEvent).Set(), done);
done.WaitOne();
}
}
}
執行結果(可以看到在.Net 5和.Net Core 3.1性能相差不大,是因為在.Net 5中并沒有對ThreadPool進行改進,但對異步是有改進):
ThreadPool.QueueUserWorkItem在.Net 5和.Net Core 3.1性能對比,沒有改進
MemoryDiagnoser使用MemoryDiagnoser這個使用較多,當時寫博客的時候,筆記本散熱不太好,這一塊跳過去了.
[MemoryDiagnoser] //使用MemoryDiagnoser特性标記
public class StringCreateTest
{
[Benchmark(Baseline = true)]
public void ArrayTest()
{
//省略測試代碼
}
}
BenchmarkDotNet 顯示測試方法所分配内存大小
v0.12.1 生成跨平台彙編代碼
using System;
using BenchmarkDotNet.Attributes;
namespace dotnet_perf
{
[DisassemblyDiagnoser(printSource:true)]
[RyuJitX64Job]
public class TestJit
{
private B[] _array = new B[42];
[Benchmark]
public int Ctor() => new Span<B>(_array).Length;
}
class A
{
}
sealed class B : A
{
}
}
//多版本測試
dotnet run -c Release -f net48 --runtimes net48 netcoreapp31 netcoreapp50 --filter ** --join
BenchmarkDotNet 生成多個平台的彙編代碼,支持Linux
BenchmarkDotNet 生成彙編代碼,和原先不一樣,原先是要到ObjDump.exe(是需要安裝MingW/Cygwin),現在需要iced庫(純C#代碼實現,另外有Rust實現).說起這個比較坑.BenchmarkDotNet v0.12.1 依賴的iced 1.4.0版本,使用新版本,是有異常的.iced庫目前隻支持X86架構(32位和64位),看代碼中沒有Arm相關的目錄,應該是不支持的.
BenchmarkDotNet 生成彙編代碼對比,發現.Net 5生成彙編代碼更小,說明性能也更好
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!