我可以用什么资源来学习分析/优化?

我刚刚inheritance了一个C#项目,该项目运行缓慢,必须开始优化它。 我首先要做的是学习更多关于分析/优化的知识,因为我以前没有这么做。 所以问题是我从哪里开始,我可以阅读哪些书籍/博客/关键词?

我知道像ANTS分析器这样的.net分析器等等,但我不知道如何有效地使用它们。 我还没有真正使用它,只是让它运行在几个示例应用程序上来播放输出。

优化代码有两个步骤。

首先,你需要找出什么是缓慢的。 这是分析,并且,正如您可能猜到的,分析器通常用于此。 大多数分析器通常都很简单易用。 您通过分析器运行您的应用程序,当它终止时,分析器将显示每个函数花费了多少时间,独占(此函数不计算从该函数调用的函数所花费的时间)以及包含(在此中花费的时间)函数,包括子函数调用)。

换句话说,你得到一个大的呼叫树,你只需要追捕大数字。 通常,您只有很少的函数占用超过10%的执行时间。 所以找到这些,你知道要优化什么

请注意,分析器既不是必需的,也不一定是最好的方法。 一种非常简单但有效的方法是在调试器中运行程序,并在几个准随机时间暂停执行并查看调用堆栈。 这样做只需要几次,并且您非常了解执行时间的花费。 根据这个答案评论的@Mike Dunlavey已经在其他地方深入描述了这种方法。

但是现在你知道执行时间花在哪里,那么棘手的部分是如何优化代码。

当然,最有效的方法通常是高级方法。 问题是否必须以这种方式解决? 是否必须要解决? 它可以提前解决并缓存结果,以便在应用程序的其余部分需要时可以立即交付吗? 是否有更有效的算法来解决问题?

如果您可以应用此类高级优化,请执行此操作,查看是否充分提高了性能,如果不是,请再次进行配置。

迟早,您可能不得不深入研究更低级别的优化。 这是一个棘手的领域。 今天的计算机非常复杂,从中获得的性能并不简单。 分支或函数调用的成本可根据上下文而有很大不同。 将两个数字加在一起可能需要0到100个时钟周期,具体取决于两个值是否已经存在于CPU的寄存器中,当时正在执行的是什么,还有许多其他因素。 因此,在这个级别进行优化需要(1)很好地理解CPU的工作原理,以及(2)大量的实验和测量。 您可以轻松地进行您认为会更快的更改,但您需要确定,因此请在更改之前和之后测量性能。

有一些通用的经验法则通常可以帮助指导优化:

I / O很贵。 CPU指令以几纳秒的分数进行测量。 RAM访问大约为几十到几百纳秒。 硬盘访问可能需要数十毫秒 。 通常,I / O会降低您的应用程序速度。 您的应用程序是执行少量大I / O读取(读取一个大块中的20MB文件),还是无数小块(从一个文件读取字节2,052到2073,然后从另一个文件读取几个字节)? 较少的大读取可以使您的I / O速度提高几千倍。

Pagefaults也涉及硬盘访问。 必须将内存页面推送到页面文件,并且必须将已分页的页面读回内存。 如果这种情况发生了很多,那就会很慢。 您可以改善数据的位置,以便同时需要更少的页面吗? 您是否可以为主机购买更多RAM,以避免不得不将数据分页? (作为一般规则,硬件很便宜。升级计算机是一个非常有效的优化 – 但要确保升级会有所作为。通过购买更快的计算机,磁盘读取速度会快得多。如果一切都适合RAM在你的旧系统上,用8倍的RAM购买一个没有意义)

您的数据库也依赖于硬盘访问。 那么你能不能在RAM中缓存更多数据,只是偶尔将其写入数据库? (当然那里存在风险。如果应用程序崩溃会发生什么?

然后是每个人最喜欢的线程。 现代CPU可提供2到16个CPU内核。 你在使用它们吗? 你会从使用它们中受益吗? 是否存在可以异步执行的长时间运行操作? 应用程序在单独的线程中启动操作,然后可以立即恢复正常操作,而不是阻塞直到操作完成。

基本上,使用分析器来了解您的应用程序。 它如何花费执行时间,花在哪里? 内存消耗是一个问题吗? 什么是I / O模式(硬盘和网络访问,以及任何其他类型的I / O)? CPU是不是一直在搅拌,还是在空闲等待一些外部事件,例如I / O或定时器?

然后尽可能地了解它正在运行的计算机。 了解它可用的资源(CPU缓存,多个内核),以及每个资源对性能的意义。

这一切都很模糊,因为优化大型数据库服务器的技巧将与您优化某些大数字运算算法的技巧大不相同。

我正在攻读本科课程(一个主题是性能分析),推荐的文本是计算机系统性能分析:实验设计,测量,模拟和建模技术 。 这是一个关于这个主题的圣经,可能有点矫枉过正。

如果您熟悉并且已经购买了ANTS(一个非常精细的分析器),那么请到这里获取快速教程以帮助您开始运行。

如果您有Visual Studio Team System,我建议使用它包含的Profiler。
它位于“Analyze-> Profiler”下
使用此分析器非常简单。 你可以潜入,看看你做了什么。 练习的实践比你将要阅读的任何文章或书更好。

只需点击几下即可轻松找到您的第一个瓶颈。 解决它们可能会变得更加棘手,但同样,优化代码只是一个问题或实践和经验。

阅读Rico Mariani的博客 。 在他升职之前,他是.Net的主要表现调整人。 他博客中的旧条目有很多好建议。 我会从接近开始,继续前进。

那,加上你已经找到的文章(特别是第一篇 )应该让你开始。

有分析器和性能分析工具,但是当你试图找到/购买/安装/学习一个时,只需尝试一个老式的诀窍……

在IDE下运行应用程序,当它处于缓慢状态时,点击“暂停”按钮,询问它正在做什么,以及为什么 。 回答这个问题的最好方法是阅读调用堆栈。

如果它比它应该慢几倍,比如10次,这意味着它花费90%的时间做一些不必要的事情, 那就是你抓住它做它的可能性 。 如果您多次重复此操作,您可以尽可能准确地确认您的怀疑。

因此,您不需要昂贵/流行但模糊的放大镜。

因此找到缓慢的原因不是困难的部分,通常有几个。

困难的是,在你修复了一些“低悬的果实”之后,你可能不得不面对这样一个事实,即缓慢的主要原因是过度设计。

祝好运。

我之前使用过分析器,它们可以提供帮助,但是你可以通过创建一个单一的秒表类型类并“点击”它来获得很多帮助(让它打印出自上次点击以来的时间以及刚刚完成的操作花了那个时间)你认为可能有问题的方法之前和之后。

如果速度在整个应用程序中都是一个问题,那么你可能无法做太多关于它的事情,但你可能会做出一些改变……

寻找内环。 这些是性能死亡。 内循环可以由简单的索引到链表中,或者对基于数组的列表进行插入排序。 (一旦我有一个列表框需要花费10-20分钟来填充成千上万的条目,尽管条目太多,最糟糕的是它通过将每个条目插入到数组列表中来对其进行排序)。

查看基于按键进行长时间操作的情况。 这几乎应该总是在主线程之外完成。

甚至不要认为优化诸如类的数量或它们被实例化的频率,字符串连接(在循环之外),使变量或任何其他看似他们应该帮助的愚蠢策略。 我已经尝试了一些,当我实际上放慢速度时总是感到愚蠢,因为我不像运行时那么聪明。

我会下载一些可用的分析工具(免费试用版)并开始使用它们。

我使用过jetbrains ,还有其他人。 ( 例如 , ant , devpartner和MS one? , atomatedqa等)运行它们不应该有太多问题。 他们有报告为您提供大量信息,您只需使用应用程序即可快速学习。

他们中的任何一个都可能对你有帮助,使用这些试验也很好。 然后你可以放弃购买工具的决定,或购买最有用/最容易使用的工具。 一般来说,他们是节省时间和物有所值的人,尽管有些人可能很贵。 (当有非常好的工具可以少花钱时,我很难处理高端的那些)

在安装和运行它们的第一天,您可能会发现一些严重/重大的性能问题。 我知道我做到了。

祝好运。

只需下载一些工具并开始运行您的应用程序。

编辑:

至于书籍和学习 – 基本上了解代码问题的最好方法是找到错误的代码。 很多时候与经验丰富的开发人员进行检查会很有帮助。

作为一个例子:我认为乔尔写了一篇关于他做了类似事情的文章

for(int i = 0; i

很明显,你将在循环的每次迭代中调用strlen(昂贵)。

在探查器告诉您何时花费时间并查看代码是否可以通过简单的事情轻松修复,或者必须在算法设计中进行更改之后,您必须查看一些代码。

这两篇文章是我发现的所有文章:

使用Visual Studio Profiler查找应用程序瓶颈

衡量.NET应用程序性能

这对C#没什么帮助,但是OS X Shark工具(Apple的开发工具附带)是我遇到过的最好的分析工具。 使用起来几乎很有趣!

至于剖析,有两种方法。 首先,您应该了解该软件。 特别是数据结构。 除非您首先理解,否则不要开始优化。

其次,你应该衡量 (这似乎你将要做)。 我的直觉几乎总是误导我; 我认为次要的地方是时间。 这也意味着当您进行优化时,您始终会针对您运行的某组测试用例进行优化。 选择此类案件很重要。

你已经用Profiler击中了头部。 所有这些,至少我使用过的所有内容,都遵循相同的基本方法。 您选择可执行文件,然后运行该应用程序。

你对输出做的是找到花费最多时间的方法。这不是全部,但你要求学习如何优化代码的好方法,所以长时间运行的例程是一个很好的起点。 您提到的ANTS将默认显示长时间运行的例程,大多数(如果不是全部)其他例程也是如此。

你可以排除容器方法,比如Main(),除非你有很多代码(不太可能)。

总的来说,我发现大多数浪费在三个方面:

  1. 循环
  2. 递归
  3. 网络延迟

对于数据库,区域#3通常很容易发现,如果您还要对数据库进行概要分析,因为您将看到命中数。 无论是否为数据库(例如,服务调用),减少网络延迟的最佳方法是在消息而不是CRUD中进行通信。 不要一次查询每个表。 不幸的是,该解决方案通常需要assembly许多常见数据层的部分。

递归和循环是非常相似的问题。 如果你想要降压,先击中内环。

在.NET中,您还可以通过学习基本IL并通过Reflector等工具检查应用程序的IL来学习很多关于优化的知识。 有点浪费时间,如果这不是你工作描述的主要部分,或者你可能想要花费你未来职业生涯的事情。 作为一名消防员付出的代价很高,但作为一名只维护编码器的人可能会非常无聊。

关于优化和分析.NET应用程序的书籍只有几本。 在标题中有所优化的那个。 .NET的调试书有关于性能分析的一些信息,但它不是很深。 这是一本很好的书,可供阅读以进行优化,因为许多导致错误的问题也会出现在您的优化行程中。