编写高性能C#代码的动机 C#性能之旅:第1部分

为什么要编写高性能代码?

我一直对MVC框架和.NET Core等内部事务感兴趣。通过了解Microsoft团队如何设计和构建框架,我觉得我提高了自己的编码能力,我可以更好地利用产品。自.NET Core和ASP.NET Core 1.0以来,团队一直关注的一点是性能。在过去一年左右的时间里,这已经有了更大的优先级,因此引入了新的类型和运行时功能来支持高性能方案。我看过.NET社区的一些知名人士谈到和发布有关性能的文章,我认为现在是时候我也要深入了解一下。

我在Twitter上关注了很多来自微软和.NET社区的优秀人才,并获得了每日灵感内容。查看其他开发人员的帖子,这些开发人员使ASP.NET Core更快,更高效,并在他们的工作中使用新的语言和框架功能,这非常鼓舞人心。作为一名自学成才的开发人员,我经常觉得我应该更多地了解我所理解的任何事情。许多与性能相关的新功能对我来说都是一个谜。我从概念层面理解它们存在并且它们正在改进软件,但我常常不确定为什么,更重要的是,它们是如何做到这一点的。

我不明白的一切; 我喜欢学习,所以我花时间阅读博客文章中的表演主题,观看视频和参加会议讲座。这个列表太大了,无法在此列出,但对我来说,一些关键的灵感是:

编写 Ben Watson

Pro .NET内存管理的高性能.NET代码: Konrad Kokosa提供更好的代码,性能和可扩展性 Adam Sitnik的

博客和演讲 Marc Gravell的

帖子

.NET社区的许多成员发布的推文,包括Ben Adams和David Fowler的

微软博客作者:Stephen Toub

这绝不是一份详尽的清单。我从更广泛的社区消费了很多很棒的帖子和信息。我非常感谢我们有很多内容!

什么是表现?

当我谈到本系列中的高性能时,我指的是两个主要概念。第一个是使代码运行得更快,以便操作花费更少的时间来完成。在Web应用程序的上下文中,这可能导致更快的页面加载时间或更快的API响应。对于处理一些进入数据以生成输出的服务工作者样式应用程序,这涉及处理的总体吞吐量。从我的角度来看,第二个重要因素是减少内存使用和分配。这两个概念在我的脑海中汇聚为“做得更多,更少”。

A typical example of where I see performance being a focus for my day-to-day work is in data processing workflows. A lot of my time is spent developing functionality which supports ingesting some data, usually via an AWS queue, and performing some work based on that message. Many of our services have grown and developed over time and today are processing large volumes of data. One such example at work is a queue processor which handles around 17-20 million messages per day. After reading the message, a workflow processes the data, validating it, enriching it and shaping it ready for storage to S3 and an ElasticSearch cluster. This process isn’t hugely complex, but due to the volume, we have periods where we have to horizontally scale our container instances to ensure we continue to achieve the desired throughput.

我们可以更高效,我们可以减少处理时间和内存消耗吗?我绝对相信我们可以。

通常,这两个表现的支柱本质上是相互联系并影响一个,可以影响另一个。例如,减少代码中的内存分配可以减少GC负载并减少收集过程引起的暂停,从而可以提高整体速度。

过早优化问题

It’s worth me addressing the elephant in the room that’ll likely become a point of debate for many as I progress through this series. Am I prematurely optimising and spending too much time in the depths of complex, performance-focused code? That may be the case in some of my examples. I’m conscious that the steps I am using often take longer to code, are less readable in some cases and therefore add debt should the code need changes in the future. I’m attempting to push the limits in my experiments in order to find the right place to draw the line.

我不是过早优化这个术语的忠实粉丝,因为它有时会在讨论中被抛出太快而导致性能被完全忽略。我坚信性能应该是我们所写的所有代码的一个特征,或多或少。决定它的重要性以及关注的重点应该是故事规划中的前期讨论。在我看来,团队应该了解他们正在构建的每个功能的要求。他们应该审查预期的使用和预期的长期增长,以便恰当地讨论可能影响绩效的领域。

有时这可能意味着不需要特定的操作,有时可能会识别出应该在早期考虑的巨大的未来扩展需求,以便尽早采取措施避免将来完全重写。当我在这里谈论性能时,它可以简单到确保通过Entity Framework进行的查询使用AsNoTracking支持来减少开销,或者它可能意味着自定义解析字节数据以避免分配。应该通过前期的早期讨论来确定适当级别的范围。

我不是在提倡每个人都花费数周的时间来重写现有代码以使用Span 以及许多其他闪亮的.NET Core功能。我所倡导的是了解编写快速,低分配代码的工具,以便为何时适当使用它们做出决策。如果您有难以跟上的代码或服务,请安排一些时间来检查问题。对应用程序进行基准测试和分析,以了解有关问题的更多信息,并在适当的情况下,开始使用一些新工具来改进代码并稳定服务。

我举了一个我维护的队列处理器的例子,它处理了数百万个事件。当它在两年半前首次在.NET Core 1.0中编写时,我们做出了一些当时有效的选择。随着它的使用不断增长,我们更全面地了解这些要求,现在我们计划进行审查。我们当前扩展实例以处理负载的解决方案运行良好,但我相信如果我们减少经常扩展的需求,我们可以节省资金。作为一项业务,我们需要平衡变更成本与通过扩展进行补偿的成本。


分享到:


相關文章: