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;按回车键进入接口模式设置。 使用…

linux iptables导致httpd网页打不开

问题&#xff1a;httpd 服务已启动&#xff0c;80端口已开&#xff0c;但是网页就是打不开&#xff0c;重启服务器还是不行 忽然想看看log&#xff0c;记录如下&#xff1a; [Fri Jul 15 00:41:03 2011] [notice] SELinux policy enabled; httpd running as context root:syste…

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

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

extjs 前端js代码调用后台函数方法

前端javascript代码部分&#xff1a; Ext.Ajax.request( { url: /Process/SuspendWorkFlow, //配置的后台函数路由 params: { wfInsId: wf.WFInstanceID, status: cmd }, //对应函数的参数 success: function () { LaunchedWFGrid.store.reload(); Ext.Msg.show({ title: &qu…

linux卸载android studio,mac上完整卸载删除.简单粗暴无脑:androidstudio删除方案

如果你是mac ,你删除as ,删不干净也正常,你会发现安装的时候,前面的东西也在.配置文件在,会导致你以前的错误不想要的东西都在.废话不多说,复制粘贴就是干!!!!~~~~~~~~第一步: 复制粘贴就是干!!!!~~~~~~~~ 复制到命令行里面,直接回车就OKrm -Rf /Applications/Android\ Studi…

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;正是给大家呈现一些…

python基金会主席入门教程_Python基金会-文件IO操作,python,基础

函数功能open打开文件read读取文件write写文件close关闭文件readline行读取readlines多行读取open方法open方法&#xff1a;打开一个文件&#xff0c;返回一个文件对象(流对象)和文件描述符&#xff0c;打开文件失败则抛异常三步曲&#xff1a;创建文件&#xff0c;打开文件&am…

Sys.WebForms.PageRequestManagerTimeoutException:服务器请求超时

Sys.WebForms.PageRequestManagerTimeoutException:服务器请求超时 在页面上使用Ajax技术时&#xff0c;当页面的程序持续时间较长时&#xff0c;程序突然会中断&#xff0c;出现上述错误&#xff0c;最后查阅资料发现ScriptManager的AsyncPostBackTimeout异步请求是有时间限制…

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

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

linux e514写入错误,Linux上使用vim编辑文件保存时报错:E514: write error (file system full?)...

今天在Linux上使用vim编辑文件保存时报如下错误E514: write error (file system full?)从错误看&#xff0c;是磁盘满了&#xff0c;于是使用df -hl查看磁盘使用情况$ sudo df -hlFilesystem Size Used Avail Use% Mounted on/dev/mapper/vg_myserver-lv_root 50G 43G 4.6G 91…

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

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

链接链接新手变化需要注意哪些问题

昨天“新手高速早期排名提升的关键因素 ”seo文章中提到不包含在预。没有排名&#xff0c;没有交通情况只有通过链接重量提升&#xff0c;不过&#xff0c;昨天的帖子时&#xff0c;有一个提为好友。除非你是一个人或资源非常丰富的静脉。情链接也不是非常好换&#xff1f;相信…

[转载]工作面试时最难的25个问题

原文地址&#xff1a;工作面试时最难的25个问题作者&#xff1a;zcan准备是成功的一半 如果你是一个对目前的职位不满意&#xff0c;正着手去在新的一年里找到一个新的职位&#xff0c;这篇文章就是你的一个帮手。工作面试是你去面对未来的老板的征途中最重要的一个过程。你必须…

ASA 第五天实验

Failover的需求 • 相同的型号和硬件配置&#xff08;接口数量和模块&#xff09; • 相同的软件版本* • 相同的加密特性&#xff08;DES or 3DES&#xff09; • 相同大小的flash和RAM* 一、配置StatefulAS Lan-based FO 步骤一、 hostname ASA interface Ethernet0/0 nameif…

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

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

linux+awk忽略tab符号,awk 如何避免文本中出现特殊符号的影响?

纯 awk 的解决方案&#xff0c;parse_csv 函数通过第一个返回一个 awk 数组&#xff0c;包含分隔好的 CSV 字段&#xff0c;直接用下标取值使用就可以了。注意&#xff0c;awk 的数组下标从 1 开始。# parse csv files to an awk array.awk -F, {parse_csv(r);# replace follow…