五个 .NET 性能小贴士

原文:bit.ly/3wSpO4o
作者:Nikita Starichenko
翻译:精致码农

大家好!今天我想和大家分享几个 .NET 的性能小贴士与基准测试。

我的系统环境:

  • BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19042.985

  • Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores

  • .NET SDK=5.0.104

我将以百分比的形式提供基准测试结果,其中 100% 是最快的结果。

1用 StringBuilder 拼接字符串

我们知道,字符串 string 是不可变的。因此,每当你拼接字符串时,就会分配一个新的字符串对象,并填充内容,最终被回收。所有这些都有昂贵开销,这就是为什么 StringBuilder 在字符串拼接时总有更好的性能。

基准测试例子:

private static StringBuilder sb = new();[Benchmark]
public void Concat3() => ExecuteConcat(3);
[Benchmark]
public void Concat5() => ExecuteConcat(5);
[Benchmark]
public void Concat10() => ExecuteConcat(10);
[Benchmark]
public void Concat100() => ExecuteConcat(100);
[Benchmark]
public void Concat1000() => ExecuteConcat(1000);[Benchmark]
public void Builder3() => ExecuteBuilder(3);
[Benchmark]
public void Builder5() => ExecuteBuilder(5);
[Benchmark]
public void Builder10() => ExecuteBuilder(10);
[Benchmark]
public void Builder100() => ExecuteBuilder(100);
[Benchmark]
public void Builder1000() => ExecuteBuilder(1000);public void ExecuteConcat(int size)
{string s = "";for (int i = 0; i < size; i++){s += "a";}
}public void ExecuteBuilder(int size)
{sb.Clear();for (int i = 0; i < size; i++){sb.Append("a");}
}

结果:

1. 3 string concatenations - 218% (35.21 ns)
2. 3 StringBuilder concatenations - 100% (16.09 ns)1. 5 string concatenations - 277% (66.99 ns)
2. 5 StringBuilder concatenations - 100% (24.16 ns)1. 10 string concatenations - 379% (160.69 ns)
2. 10 StringBuilder concatenations - 100% (42.37 ns)1. 100 string concatenations - 711% (2,796.63 ns)
2. 100 StringBuilder concatenations - 100% (393.12 ns)1. 1000 string concatenations - 3800% (144,100.46 ns)
2. 1000 StringBuilder concatenations - 100% (3,812.22 ns)

2赋予动态集合初始大小

.NET 提供了很多集合类型,比如 List<T>, Dictionary<T>, 和 HashSet<T>。所有这些集合都有动态的容量,当你添加更多的项目时,它们的大小会自动扩大。

当集合达到其大小限制时,它将分配一个新的更大的内存缓冲区,这意味着要进行额外的开销去分配容量。

基准测试例子:

[Benchmark]
public void ListDynamicCapacity()
{List<int> list = new List<int>();for (int i = 0; i < Size; i++){list.Add(i);}
}
[Benchmark]
public void ListPlannedCapacity()
{List<int> list = new List<int>(Size);for (int i = 0; i < Size; i++){list.Add(i);}
}

在第一个方法中,List 集合使用默认容量初始化,并动态扩大。在第二个方法中,初始容量被设置为它所需要的固定大小。

对于 1000 个项目,其结果是:

1. List Dynamic Capacity - 140% (2.490 us)
2. List Planned Capacity - 100% (1.774 us)

DictionaryHashSet 的测试结果是:

1. Dictionary Dynamic Capacity - 233% (20.314 us)
2. Dictionary Planned Capacity - 100% (8.702 us)1. HashSet Dynamic Capacity - 223% (17.004 us)
2. HashSet Planned Capacity - 100% (7.624 us)

3ArrayPool 用于短时大数组

数组的分配和回收的开销可能是相当昂贵的,高频地执行这些分配会增加 GC 的压力并损害性能。一个优雅的解决方案使用是 System.Buffers.ArrayPool 类,它可以在 NuGet 的 Systems.Buffers 中找到。

这个思想和 ThreadPool 很相似。为数组分配一个共享缓冲区,你可以重复使用,而不需要实际分配和回收它们占用的内存。基本用法是调用 ArrayPool<T>.Shared.Rent(size),这将返回一个常规数组,你可以以任何方式使用它。完成后,调用 ArrayPool<int>.Shared.Return(array) 将缓冲区返回到共享池中。

基准测试例子:

[Benchmark]
public void RegularArray()
{int[] array = new int[ArraySize];
}
[Benchmark]
public void SharedArrayPool()
{var pool = ArrayPool<int>.Shared;int[] array = pool.Rent(ArraySize);pool.Return(array);
}

ArraySize = 1000 的结果:

1. Regular Array - 2270% (440.41 ns)
2. Shared ArrayPool - 100% (19.40 ns)

4结构代替类

当涉及到对象回收时,Struct 有如下几个好处:

  • 当结构类型不是类的一部分时,它们被分配在堆栈中,根本不需要垃圾回收。

  • 当结构是类(或任何引用类型)的一部分时,它们被存储在堆中。在这种情况下,它们是内联存储的,并且会随包含类型回收而回收。内联意味着该结构的数据是按原样存储的,这与引用类型相反,在引用类型中,指针被存储到堆上另一个位置。所以回收的成本要低很多。

  • 结构比引用类型占用的内存更少,因为它们没有 ObjectHeaderMethodTable

基准测试例子:

class VectorClass
{public int X { get; set; }public int Y { get; set; }
}struct VectorStruct
{public int X { get; set; }public int Y { get; set; }
}private const int ITEMS = 10000;[Benchmark]
public void WithClass()
{VectorClass[] vectors = new VectorClass[ITEMS];for (int i = 0; i < ITEMS; i++){vectors[i] = new VectorClass();vectors[i].X = 5;vectors[i].Y = 10;}
}[Benchmark]
public void WithStruct()
{VectorStruct[] vectors = new VectorStruct[ITEMS];// At this point all the vectors instances are already allocated with default valuesfor (int i = 0; i < ITEMS; i++){vectors[i].X = 5;vectors[i].Y = 10;}
}

结果:

1. With Class - 742% (88.83 us)
2. With Struct - 100% (11.97 us)

5ConcurrentQueue<T> 代替 ConcurrentBag<T>

在没有基准测试的情况下,不要使用 ConcurrentBag<T>。这个集合是为非常特殊的使用场景而设计的(当经常有项目被排队的线程删除时)。如果需要一个并发的集合队列,请选择 ConcurrentQueue<T>

基准测试例子:

private static int Size = 1000;[Benchmark]
public void Bag()
{ConcurrentBag<int> bag = new();for (int i = 0; i < Size; i++){bag.Add(i);}
}[Benchmark]
public void Queue()
{ConcurrentQueue<int> bag = new();for (int i = 0; i < Size; i++){bag.Enqueue(i);}
}

结果:

1. ConcurrentBag - 165% (24.21 us)
2. ConcurrentQueue - 100% (14.64 us)

感谢大家阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java程序弊端_面向对象编程的弊端是什么?

信仰万物皆对象&#xff0c;习惯性Thinking in OOP的话&#xff0c;有可能会限制住自己解决实际问题的思路。曾经面试过某java候选人&#xff0c;我出了道其实很简单的算法题。结果候选人上来就去定义对象、属性、方法、接口等等&#xff0c;企图去搭一个面向对象的『框架』来解…

Javascript函数调用的四种模式

Javascript一共有四种调用模式&#xff1a;方法调用模式、函数调用模式、构造器调用模式以及apply调用模式。调用模式不同&#xff0c;对应的隐藏参数this值也会不同。 函数作为对象的属性时&#xff0c;称为方法。此时函数&#xff08;即方法&#xff09;中的this对应是该对象…

【推荐】BREW中 - 显示和图像

a. BREW 支持哪些图像格式&#xff1f; 适用版本&#xff1a; 1.0, 1.1, 2.0 BREW 支持颜色深度达到运行设备上提供的值的任何 BMP 文件。 BREW 目前尚不支持 GIF 和 JPEG 图像。 有些设备可以支持 GIF 和 JPEG 图像&#xff0c;请参阅设备数据表来查看 OEM 是否提供了支持以上…

我背着女朋友,用 Python 偷偷抓取了她的行踪

全世界只有3.14 %的人关注了青少年数学之旅1目 标 场 景有时候女朋友一个人在外面玩耍&#xff0c;问她在哪个地方&#xff0c;就是不告诉我。但是&#xff0c;你又很想知道女朋友的「位置」&#xff0c;这该如何是好&#xff1f;其实你可以这样套路女朋友&#xff0c;假装自己…

ASP.NET Core 中的规约模式(Specification Pattern )——增强泛型仓储模式

原文链接&#xff1a;https://codewithmukesh.com/blog/specification-pattern-in-aspnet-core/在本文中&#xff0c;我们将讨论在 ASP.NET Core 应用程序中实现规约模式以及它如何增强现有的泛型仓储模式。我们将从头开始构建具有泛型仓储模式、Entity Framework Core的 ASP.N…

面向过程的ado建造者模式

{*******************************************************}{ }{ ADO数据工厂 }{ }{ 版权所有 (C) 2008 咏…

Javascript:this用法

#Javascript&#xff1a;this用法整理pingan 于 星期三, 18/12/2013 - 22:32 提交 常用Javascript的人都知道&#xff0c;&#xff3b;this这个关键字在一个函式内究竟指向谁&#xff3d;的这个问题很令人头大&#xff0c;本人在这裡整理了一下Javascript中this的指向的五种不同…

动画演示男性结扎手术 | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅流鼻涕了怎么办&#xff1f;医学教育徐琦招聘程序员啦知识萌死大丧失&#xff1b;图熊本科技把下列句子补充完整图三好学生李宇幼年的大象喝水并不会使用鼻子而是趴在水里直接用嘴大喝一顿它们9个月之后才会懂得用鼻子喝水科普斯基请…

MYSQL 只能回环口链接_loopback回环口详解

在配置OSPF路由协议的时候配置回环(loopback)接口是很重要的1件事.Cisco建议你配置OSPF的时候顺便配置回环接口.所谓回环接口,是逻辑接口而非物理接口,即不是你触摸的到的router上的真正的接口.作用是作为诊断OSPF而用.如果router的某一个接口由于故障down掉而不可用了,此时你怎…

AspNetCoreMassTransit Courier实现分布式事务

在之前的一篇博文中&#xff0c;CAP框架可以方便我们实现非实时、异步场景下的最终一致性&#xff0c;而有些用例总是无法避免的需要在实时、同步场景下进行&#xff0c;可以借助Saga事务来解决这一困扰。在一些博文和仓库中也搜寻到了.Net下实现Saga模式的解决方案MassTransit…

可能会紧急用到的Linux命令

查看当前网络连接数&#xff1a; netstat -na|grep ESTABLISHED|awk {print $5}|awk -F: {print $1}|sort|uniq -c|sort -r -n删除掉不以java和xml结尾7天没有使用的文件 : find . ! -name *.java ! -name *.xml -atime 7 -exec rm {} \;转载于:https://blog.51cto.com/guihai…

设置列表字段为主键

转贴:Sample event handler to set a field as a pr imary key (enforce no duplicates) Got this as a request from a reader- how to prevent users from adding items with same titles as ones that already exist in the list. Codeusing System;using System.Collectio…

被学校辞退、拒绝FB后:语音识别大牛Povey确认兼职北京初创公司,称主业还选中国...

全世界只有3.14 % 的人关注了青少年数学之旅由于5月的学生抗议事件&#xff0c;语音识别领域著名学者、原约翰霍普金斯大学教授Daniel Povey被学校辞退。随后&#xff0c;Daniel Povey准备进入Facebook从事语音识别系统的开发&#xff0c;但是由于Facebook要对其进行长达6周的审…

也谈子网划分和子网通信

子网划分和子网通信在小型网络中应用不多&#xff0c;但随着公司规模的扩大&#xff0c;这样的问题就会提上网管的工作计划。资料略加整理&#xff0c;希望对各位有帮助。也谈子网划分和子网通信1.网络IP地址和子网掩码的分类&#xff1a;A类&#xff1a;IP: 0.0.0.0 &#xff…

java io流学设置编码_Java学习日志(21-2-IO流-基本数据类型与字节数组对象与、编码解码)...

操作基本数据类型的流对象DataStream/*可以用于操作基本数据类型数据的流对象*/import java.io.*;class DataStreamDemo{public static void main(String[] args)throws IOException{// writeData();// readData();// writeUTFDemo();// OutputStreamWriter oswnew OutputStrea…

dotnet中的counters说明(二)

上篇说了System.Runtime&#xff0c;它负责应用运行的环境资源的收集&#xff0c;这篇要继续说AspNetCore的Hosting,Http.Connections和Server.Kestrel三个计数器。同时&#xff0c;下面指标各项()里的项目是--counters 参数[]里的项&#xff0c;用逗号分隔多项指标。Microsoft…

Asp组件中级入门与精通系列之五

我们学习来看一下Response对象。其实我们前面的教程中一直都在使用这个对象的Write方法。 这里我们用Response对象设置cookie。 ? 打开vb6,新建Activex Dll工程。工程名修改为fCom,类名修改为fZ5 引用“Microsoft Active Server Pages Object”对象库。 创建两个组件事件&…

有这些好习惯,可以让你悄悄变优秀

全世界只有3.14 %的人关注了青少年数学之旅这是一个普遍无趣的时代&#xff0c;很多人看似忙到起飞内在却空虚迷茫。今天我们为你诚意推荐几个公众号它们会成为你生活的一剂调味料&#xff0c;让你做一个学识丰富、灵魂有趣的人。快来关注&#xff0c;开启精彩的生活吧&#xf…

java设置access-allow_Java Web如何设置多个Access-Control-Allow-Origin

有没有办法让Access-Control-Allow-Origin header允许设置multiple cross-domains呢&#xff1f;如果设置response.addHeader("Access-Control-Allow-Origin","*");感觉这个接口太开放了&#xff0c;不太安全。 我想只设置自己指定的若干个域名或者端口可以…

paip.提升用户体验--提升java的热部署热更新能力

paip.提升用户体验--提升java的热部署热更新能力 想让java做到php那么好的热部署能力 "fix online"/在线修复吗&#xff1f;&#xff1f;直接在服务器上修改源码生效&#xff0c;无需重启应用。。作者Attilax 艾龙&#xff0c; EMAIL:1466519819qq.com来源&#x…