C#提升性能的几点提示和技巧


C#性能提示和技巧

在Raygun[1],我们是一群非常懂多种语言的开发人员。Raygun的各个部分使用不同的语言和框架编写-最好的工作方式。

鉴于大量的C#和我们正在处理的数据的爆炸性增长,在不同的时间需要进行一些优化工作。大部分重大的收获往往来自于真正地重新思考问题并从全新的角度解决问题。

今天我想分享一些C#性能技巧,这些技巧对我的最新工作有所帮助。其中一些功能在你看来也许相当微不足道,因此请不要在这里充电并使用所有功能。就这样,提示1是…

1.每个开发人员都应使用分析器

有一些很棒的.NET分析器。我个人使用了Jet Brains[2]团队的dotTrace分析器。我知道我们团队中的Jason 也从Red Gate分析器中[3]获得了很多价值。每个开发人员都应安装并使用探查器。

我无法数出我认为应用程序的最慢部分在一个区域中的次数,而实际上却完全在其他地方。探查器对此提供了帮助。此外,有时候,它可以帮助我发现错误-缓慢的部分之所以缓慢,只是因为它做错了什么(单元测试

没有

正确地拾取它)。

这是您要执行的所有优化工作的第一步,也是有效的第一步。

6423bd5a52f50350da826b8ecfe9b73c.png

冲刺开始

2.抽象级别越高,速度越慢(通常)

这只是我闻到的气味。您使用的抽象级别越高,通常越慢。我在这里发现的一个常见示例是在代码繁忙的部分(也许在循环中被称为数百万次)中使用LINQ。LINQ非常适合快速表达某些内容,而这些内容可能要花一堆代码,但是您通常会将性能留在桌面上。

不要误会我的意思-LINQ非常适合让您开发出可运行的应用程序。但是在代码库中以性能为中心的部分中,您可能会付出太多。特别是因为将这么多操作链接在一起非常容易。

我所使用的特定示例是我使用的地方.SelectMany().Distinct().Count()。鉴于这被称为数千万次(由我的探查器发现的关键热点),它正在累积大量的运行时间。我采用了另一种方法,并将执行时间减少了几个数量级。

3.不要低估发行版和调试版

我一直在努力工作,对获得的性能感到非常满意。然后,我意识到自己已经在Visual Studio中进行了所有测试(我经常将性能测试编写为也可以作为单元测试运行,因此我可以更轻松地运行自己关心的部分)。我们都知道发行版本已启用优化。

因此,我做了一个发布版本,称为从控制台应用程序测试的方法。

我对此有了很大的转变。我的代码已经疯狂地进行了优化,因此确实是时候对.NET JIT编译器进行一些微优化了。启用优化后,我的性能提高了约30%!这使我想起了我不久前在网上阅读的一个故事。

4dba99bca4ab34f339a0c77320b43266.png

这是上世纪90年代的一个古老游戏编程故事,当时内存限制非常严格。在开发周期的后期,团队最终将耗尽内存,并开始考虑必须删除或降级哪些内容以适合可用的微小内存空间。资深开发人员根据他的经验就曾期望这样做,并在项目一开始就分配了1MB的内存和垃圾数据。然后,他节省了一天的时间,并删除了他在项目开始时立即分配的1MB内存,从而解决了问题!

知道团队总是没有足够的空间,因为那里有可用的内存,就可以为团队提供他们所需要的东西,并按时发货。

我为什么要分享这个?在性能方面类似–在调试模式下获得足够好的运行,并且您将在发行版本中获得一些“免费”性能。美好时光。

4.看大局

有一些很棒的算法。您多数不需要每天甚至每月都不用。但是,值得知道它们的存在。我经常进行研究后,就会发现一种更好的解决问题的方法。在编码之前进行研究的开发人员与在编写代码之前进行适当分析的开发人员的可能性差不多。我们喜欢代码,并且总是想直接进入IDE。

此外,通常在查看性能问题时,我们过于专注于单个生产线或方法。这可能是一个错误–放眼全局,可以通过减少需要完成的工作来帮助您显着提高性能。

5.内存位置很重要

假设我们有一个数组数组。实际上是一张桌子,尺寸为3000×3000。我们要计算有多少个插槽的值大于零。

问题–这两个中哪个更快?

for (int i = 0; i < _map.Length; i++)
{for (int n = 0; n < _map.Length; n++){if (_map[i][n] > 0){result++;}}
}
for (int i = 0; i < _map.Length; i++)
{for (int n = 0; n < _map.Length; n++){if (_map[n][i] > 0){result++;}}
}

回答?第一个。在我的测试中,此循环使性能提高了8倍!

注意区别吗?这是我们遍历此数组数组的顺序([i] [n]与[n] [i])。即使我们从自己管理内存中抽象出来,内存局部性在.NET中的确很重要。

就我而言,这种方法被称为数百万次(准确地说是数亿次),因此我可以从中获得的任何性能都获得了可观的胜利。再次感谢我经常使用的分析器,以确保我专注于正确的地方!

6.减轻垃圾收集器的压力

C#/.NET具有垃圾回收功能。垃圾收集是确定哪些对象当前已过时并删除它们以释放内存中空间的过程。这意味着在C#中,与C ++之类的语言不同,您不必手动维护不再有用的对象的删除,即可声明其在内存中的空间。相反,垃圾收集器(GC)处理所有这些,因此您不必这样做。

问题是没有免费的午餐

问题是没有免费的午餐。收集过程本身会导致性能下降,因此您实际上并不希望GC一直收集。那么如何避免这种情况呢?

有许多有用的技术可以避免对GC施加太大压力[4]。在这里,我将只关注一个技巧:避免不必要的分配。这意味着要避免这样的事情:

List<Product> products = new List<Product>();
products = productRepo.All();

第一行创建了一个完全无用的列表实例,因为下一行返回另一个实例并将其引用分配给变量。现在想象一下上面的两行是否在一个执行数千次的循环中?

上面的代码可能看起来像一个愚蠢的示例,但是我已经在生产中看到了这样的代码,而不仅仅是一次。不要只关注示例本身,而要关注一般建议。除非确实需要,否则不要创建对象。

由于GC在.NET中的工作方式(这是一个世代的GC流程),因此较旧的对象更有可能收集较新的对象。这意味着创建许多新的,短暂的对象可能会触发GC运行。

7.不要使用空的析构函数

标题说明了一切-请勿在类中添加空的析构函数。Finalize每个具有析构函数的类的条目都会添加到队列中。然后在调用析构函数时调用我们的老朋友GC来处理队列。空的析构函数意味着这一切都是徒劳的。

请记住,就性能而言,GC执行并不便宜,正如我们已经提到的。不要不必要地导致GC工作。

73f79d71d29adce26f95d573359cbb6b.png

盒子的屏幕截图

8.避免不必要的装箱和拆箱

装箱和拆箱就像垃圾回收一样,在性能方面很昂贵。因此,我们希望避免不必要地进行操作。但是他们在实践中会做什么?

装箱就像创建引用类型框并将值类型的值放入其中一样。换句话说,它包括将值类型转换为“对象”或该值类型实现的接口类型。取消装箱相反,它会打开包装盒并从其中提取值类型。为什么会有问题呢?

好吧,正如我们已经提到的,装箱和拆箱本身就是昂贵的过程。除此之外,当您装箱一个值时,您会在堆上创建另一个对象,这给GC带来了额外的压力(您已经猜到了!)。

那么,如何避免装箱和拆箱呢?

通常,您可以通过避免.NET(版本1.0)中早于泛型的API来做到这一点,因此,它们必须依赖于使用对象类型。例如,更喜欢通用集合,例如System.Collections.Generic.List,而不是System.Collections.ArrayList

9.当心字符串连接

在C#/。NET中,字符串是不可变的。因此,每次执行一些看起来好像在更改字符串的操作时,它们都会创建一个新的字符串。这些操作包括类似的方法ReplaceSubstring,同时也串联。

提防串联大量字符串,尤其是在循环内部

因此,这里的技巧很简单-注意不要串联大量字符串,尤其是在循环内部。在这种情况下,请使用System.Text.StringBuilder类,而不要使用“ +”运算符。这样可以确保不会为连接的每个部分创建新实例。

10.随时关注C#的发展

最后,我们以非常笼统的建议作为结尾-请密切关注C#语言的更改和发展方式。C#团队不断提供可以对性能产生积极影响的新功能。

我们可以提到的一个最新示例是C#7中引入的ref[5] return 和ref locals[6]。这些新功能允许开发人员按引用返回并将引用存储在局部变量中。C#7.2引入了Span[7] 类型,从而可以对内存的连续区域进行类型安全的访问。

诸如此类的新功能和类型不太可能被大多数C#开发人员使用,但是它们无疑会对性能至关重要的应用程序产生影响,值得进一步了解。

C#性能很重要!

这只是我发现对提高.NET代码性能有用的几件事的集合-但是值得花时间检查代码以确保其性能。您的团队和客户将感谢您!

References

[1] Raygun: https://raygun.com/
[2] Jet Brains: https://www.jetbrains.com/
[3] Red Gate分析器中: http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/
[4] 许多有用的技术可以避免对GC施加太大压力: https://michaelscodingspot.com/avoid-gc-pressure/
[5] ref: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
[6] 和ref locals: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
[7] Span: https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=netcore-3.0

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

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

相关文章

电脑睡眠快捷键_电脑快速进入睡眠的快捷键是什么?

电脑快速进入睡眠的快捷键是什么&#xff1f;正常情况下需要点击电源再按睡眠&#xff0c;小编觉得有点麻烦&#xff0c;如果你想要进入睡眠状态能够像锁屏快捷键那样就好了&#xff0c;那么今天就教大家如何设置睡眠快捷键&#xff0c;让你的电脑快速进入睡眠状态。我们知道电…

世界上最奇特的国界线,万万没想到...

全世界只有3.14 % 的人关注了爆炸吧知识你曾经可能多次在飞机上切换不同的国家&#xff0c;但未曾真的看见过这些国家之间的分界线。没见过之前&#xff0c;你脑海中的国界线是怎样的&#xff1f;一道高墙&#xff1f;还是一条无法逾越的鸿沟......看似正经而严谨&#xff0c;但…

Dell poweredge r210进BIOS修改磁盘控制器(SATA Controller)接口模式

Dell poweredge r210进BIOS修改磁盘控制器&#xff08;SATA Controller&#xff09;接口模式 开机后按F2键进入BIOS设置&#xff0c;如下图&#xff1a; BIOS设置主界面&#xff1a; 使用上下键移动光标到“SATA Controller”上&#xff0c;按回车键进入接口模式设置。 使用…

二叉排序树与文件操作的设计与实现_堆排序就这么简单

一、堆排序介绍来源百度百科&#xff1a;堆排序(Heapsort)是指利用堆积树&#xff08;堆&#xff09;这种数据结构所设计的一种排序算法&#xff0c;它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆&#xff0c;是完全二叉树。前面我已经…

Tp框架如何使用事务和锁,还有查询缓存

1.事务 在ThinkPHP框架中&#xff0c;可以使用think\db\Transaction类来实现事务。 use think\Db; use think\db\Transaction;// 开始事务 Db::startTrans();try {// 执行数据库操作Db::table(user)->where(id, 1)->update([name > John]);// 提交事务Db::commit(); }…

因为没钱买衣服,我女朋友不要我了......

1 我妈为了省钱啥事都做得出▼2 高端的黄牛总是用最朴素的方法▼3 不加点什么你们觉得我阴阳怪气祖安大师怎么办&#xff1f;▼4 一天共有86400秒一天写2000首诗&#xff0c;也就是平均43.2秒一首曹植七步成诗也不过如此了▼5 如果在猫顺毛时弄乱它的毛会怎么样&#xff1…

Tech UP——EGO北京分会成立啦

古人崇敬自然&#xff0c;认为天地生万物而四时有序&#xff0c;是以春耕、夏耘、秋收、冬藏。在过去的8年里&#xff0c;InfoQ中国秉持着“促进软件开发领域知识与创新的传播”的理念&#xff0c;始终与技术人和公司在一起。经过8年的耕耘和沉淀&#xff0c;正是给大家呈现一些…

实现一个登录:Mac+.NET 5+Identity+JWT+VS Code

.NET圈儿的朋友们&#xff0c;大家好&#xff01;我可太喜欢如今开源的.Net了&#xff0c;写代码很巴适&#xff01;所以今天分享一下之前学习的一个登录小案例&#xff0c;代码有不足之处欢迎指正&#xff01;&#xff01;&#xff01;工具&#xff1a;采用VS Code及其插件开发…

天体运行动图,如此美妙,如此震撼!

全世界只有3.14 % 的人关注了爆炸吧知识三体中心天体也在运动双星系统银河系与仙女系相撞模拟转自&#xff1a;奇趣物理--完--

密封槽设计标准_哈尔滨轴承 | 超全面机械密封选型

有转动的地方&#xff0c;就有HRB轴承(400-086-6629)100多年来&#xff0c;人们采用填料一类的多种密封材料&#xff0c;使液体从液泵壳体沿着主轴的向外泄漏量不断减少。尽管现代工艺流程中采用的液泵&#xff0c;仍然广泛地沿用最古老的密封设计——填料盒&#xff0c;因为其…

重要更新,Office Add-in将全面支持Webview2

在陪娃上课&#xff0c;耳边回响着美妙的音乐&#xff0c;打开电脑码字&#xff0c;给大家分享一个非常重要的消息&#xff1a;Office Add-in将全面支持WebView2了。Office的开发爱好者可能会对此很感兴趣&#xff0c;虽然新一代的Web Add-in随着Office 365的推出&#xff0c;也…

哈佛学者:这3本英文名著,每天小读10分钟,英语level暴涨....

全世界只有3.14 % 的人关注了爆炸吧知识《锵锵》中窦文涛曾说过&#xff1a;“读原著学英语&#xff0c;就像有了可视化进度条&#xff0c;每天的提升肉眼可见。”今天就给大家推荐3本豆瓣高分英文名著&#xff0c;学英语不枯燥&#xff0c;每天小读10分钟&#xff0c;即可学到…

php -- 用文本来存储内容,file_put_contents,serialize,unserialize

根据存储的内容来划分 字符串&#xff1a; file_put_contents &#xff1a;将一个字符串写入文件 语法&#xff1a;int file_put_contents ( string $filename , mixed $data [, int $flags 0 [, resource$context ]] ) 参数 filename&#xff1a;要被写入数据的文件名。 data…

女朋友当众甩了我一巴掌,我扑上去......

1 小朋友&#xff0c;你是否有很多问号&#xff1f;▼2 小鸟&#xff1a;我呸&#xff01;秀什么秀&#xff1f;没眼看&#xff01;▼3 开学后你的上课状态......▼4 不能总让保安叔叔拿枪指我▼5 哥哥&#xff1a;让我看看&#xff0c;我妹妹怎么那么可爱&#xff01;▼6…

为什么我们要做2021.NET中国开发者调研

今年7月的时候&#xff0c;由上海MS Reactor牵头&#xff0c;我们做了一次小型的闭门会议。主要是围绕.NET开源方向进行讨论。 数闪科技的技术总监谷首道给我们带来的消息是他们有意将公司目前正在研发和使用的一整套技术框架进行开源。亲切可爱的辛老师、盛派创始人苏震巍、数…

sql连接远程服务器索引超出了_手机怎么连接服务器远程桌面?RD client远程桌面使用教程...

大家好啊&#xff0c;现在很多游戏、应用为了体验感好、方便使用都实现了多端同步&#xff0c;服务器远程连接也不例外&#xff0c;今天给你们分享手机连接服务器远程桌面的操作方法【 好东西一起分享&#xff0c;好音乐一起听 】不管是安卓还是苹果手机&#xff0c;咱们都需要…

java垃圾回收机制

为什么80%的码农都做不了架构师&#xff1f;>>> Java垃圾回收机制 C程序员觉得内存管理太重要了,所以一定需要自己管理, java程序员觉得内存管理太重要了,所以一定不能自己管理! 一、简述 垃圾回收是一种动态存储管理技术&#xff0c;它自动地释放不再被程序引用的…

神PS!老爸把儿子的画作P成现实,看完我笑哭了

全世界只有3.14 % 的人关注了爆炸吧知识只要你敢画&#xff0c;我就敢P成现实这种脑洞大开的事发生在英国的一对父子身上儿子天马行空地乱画爸爸认认真真地P出来象君几年前在ins发现了这对宝藏父子没想到他们的疯狂依旧在继续着四脚怪物系列看上去好像也没什么毛病你就是我见过…

单体应用 适合采用 dapr 构建吗?

缘起今天在微信群里有同学问 ”纯.net 项目&#xff0c;有必要上dapr吗&#xff1f;” 当时不假思索的说不是微服务没必要&#xff0c;其他群友也说没必要。下午细想了一下&#xff0c;觉得这个和微服务没有关系&#xff0c;如果我的应用是个单体架构&#xff08;将所有功能都部…

一次面试引发的思考(中小型网站优化思考) (转)

前言 故事的起因是这样的&#xff0c;由于本人地处偏僻工作地点在美丽的冰城哈尔滨虽然地方很美丽&#xff0c;但是这里的软件行业实在是算不上“美丽”&#xff0c;这么多年由于个人原因或者公司原因经常换工作&#xff0c;因为这里都是中小型公司&#xff0c;没有什么大公司。…