尝试解决问题之前,应当先理解问题

来源:互联网 发布:腾讯漏洞软件 编辑:程序博客网 时间:2024/05/17 05:01

原文出自:http://blogs.msdn.com/maoni/archive/2006/09/01/734880.aspx

版权归原文作者所有,转载请注明出处


尝试解决问题之前,应当先理解问题

 

到目前为止,还没有写过任何理论上的建议,以指导处理性能问题。最近看到很多人在性能计数器上犯难(甚至没找到正确的计数器),反复提到诸如“分配输率是否过高?对我来说好像太高了”,或者“1代对象太大了,不是么?看起来的确很大”等问题,甚至在找到足够的证据之前就开始胡乱提问猜测了。

如果是出于好奇心而提问的话,那非常好。我非常乐意回答问题或者给出参考文献。但对于那些需要调查性能相关问题,特别是最后期限将近的人,我的建议是:先理解问题所在,再解决问题。判断必须基于证据,而不是基于贫乏的领域知识。问GC相关的问题之前,先问问自己,GC是否真的是问题所在。如果不能回答,那么问GC相关的问题纯粹是浪费时间。

见过很多这样的案例:托管应用程序一出错,人们就立刻怀疑GC,即便没有任何证据。接着在不知道问题是什么的情况下,开始发问-这些问题通常极罕见-希望能找到解决问题的办法。毫无逻辑可言,不是么?

对于如何知道要解决的问题是什么,我的建议如下:

1)     了解基础知识非常有助于解决问题。

什么是基础知识?性能一般源于两个方面-内存和CPU。了解这两个方面的基础知识有助于判断应该从哪里着手。显然这涉及到大量的阅读和实践。下面列出一些关于内存的基础知识:

 

一些内存基本知识

 

每个进程有独立的虚拟地址空间;同一台机器上的所有进程共享屋里内存(还要加上分页文件,如果有的话)。默认情况下,每个32位进程有2GB用户态虚拟地址空间。

 

程序员同虚拟地址空间打交道-不会直接操作物理内存。如果写非托管代码的话,一般通过一些win32 APIcrt堆,进程堆,或者自己创建的堆)来使用虚拟地址空间-这些API为你分配和释放虚拟内存;如果是托管代码,GC为你分配/释放虚拟内存。

 

虚拟地址空间会导致碎片-换句话说,地址空间上可能有“漏洞”(自由区块)。当VM(虚拟内存)分配被请求时,VM管理器需要找到一块足够大的连续自由区块来满足请求-如果只能找到一些合计起来足够大,但不是连续区块的话,就无法完成分配。这意味着即使有2GB,也没办法完全使用他们。

 

   VM有不同的状态-自由,保留和已提交。自由状态很简单。保留和已提交状态之间的差别是迷惑人们的所在。首先,需要认识到他们是不同的状态。保留就是说“我希望让这块内存为我所用”。在保留一块VM后,这块内存将不能被分配给其他保留请求。此时,还不能存储任何数据到这块内存-必须先提交,也就是说必须先得到物理内存,然后才能存储数据。在使用性能计数器或者其他工具查看内存时,要保证看的东西是对的。如果耗尽保留空间或者提交空间,会收到Out Of Memory异常。

 

    如果有分页文件(默认情况下都有),即便物理内存很充裕,也能使用它。当第一次物理内存吃紧时,操作系统需要将当前物理内存上的一些数据备份到分页文件,以便为其他存储数据腾出空间。直到需要这些数据的时候,才会从分页文件移到物理内存上,取消对其分页,所以即使物理内存非常充裕,也能观察到分页。

 

2) 必须了解自己的性能需求是什么

 

如果正在写一个服务程序,显然你希望使用所有的内存和CPU,这没问题,因为机器完全是为了运行你的程序准备的。假如果正在写客户端程序,情况完全变了-你必须知道如何与机器上的其他应用程序共处。这里没有类似应用程序必须尽可能少的使用内存的规则。

 

一旦断定有问题,就要以深入挖掘代替猜测。如果应用程序用了太多内存,就找出是谁正占用内存。若断定是托管堆占用了太多内存,就要弄清楚为什么会这样。托管堆使用太多内存通常说明对象存活得太久,没有及时回收,需要搞清楚什么东西引用了这些对象。