我刚刚继承了一个C#项目,该项目运行缓慢,必须开始优化它.我首先要做的是学习更多关于分析/优化的知识,因为我之前没有这么做.所以问题是我从哪里开始,我可以阅读哪些书籍/博客/关键词?
我知道像ANTS分析器这样的.net分析器等等,但我不知道如何有效地使用它们.我还没有真正使用它,只是让它运行在几个示例应用程序上来播放输出.
优化代码有两个步骤.
首先,你需要找出什么是缓慢的.这是分析,并且,正如您可能猜到的,分析器通常用于此.大多数分析器通常都很简单易用.您通过分析器运行应用程序,当它终止时,分析器将显示每个函数花费了多少时间,独占(此函数不计算从该函数中调用的函数所花费的时间)以及包含(在此中花费的时间)函数,包括子函数调用).
换句话说,你得到一个大的呼叫树,你只需要追捕大数字.通常,您只有很少的函数占用超过10%的执行时间.所以找到这些,你知道要优化什么.
请注意,分析器既不是必需的,也不一定是最好的方法.一种非常简单但有效的方法是在调试器中运行程序,并在几个准随机时间暂停执行并查看调用堆栈.这样做只需要几次,您就可以很好地了解执行时间的花费.根据这个答案评论的@Mike Dunlavey在其他地方深入描述了这种方法.
但是现在您知道执行时间花在哪里,然后是棘手的部分,如何优化代码.
当然,最有效的方法通常是高级方法.问题是否必须以这种方式解决?是否必须要解决?它可以提前解决并缓存结果,以便在应用程序的其余部分需要时可以立即交付吗?是否有更有效的算法来解决问题?
如果您可以应用此类高级优化,请执行此操作,查看是否充分提高了性能,如果不是,请再次进行配置.
迟早,您可能不得不深入了解更低级别的优化.这是一个棘手的领域.今天的计算机非常复杂,从中获得的性能并不简单.分支或函数调用的成本可根据上下文而有很大不同.两数相加在一起,可以根据这两个值是否已经在CPU的寄存器,什么从0到100个时钟周期的任何地方采取其他被当时正在执行,以及许多其他因素.因此,在这个级别进行优化需要(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缓存,多个内核),以及每个资源对性能的意义.
这都是很模糊的,因为技巧来优化大型数据库服务器都将是非常从你该怎么做才能优化一些大的数字运算算法的不同.