我们以前已经讨论过很多关于各种内存管理的概念-/3GB开关的使用、x86虚拟地址空间等等。最常见的内存问题的现象就是内存不足-实质上是一种资源不足的情况。

有两种类型的内存压力需要考虑 - 第一种,一个只安装了很少的物理内存的系统。当一个只有很少内存的系统,由于虚拟内存管理器尝试把进程最近访问过的虚拟内存页保留在物理内存里面用于快速的读取,这样系统有更多的负载。应用程序和整体系统的性能都有可能受到增加的页面交换的影响。尽管过多的页面交换只是一个次要的症状,但它确实是最容易识别的症状。第二种类型的内存问题是在一个进程耗尽了有效虚拟内存的时候发生的。这就是最常说的内存泄漏。大多数内存泄漏是非常容易发现并且通常是软件代码缺陷所导致的。然而,正常系统的负载同样也会导致内存耗尽-并不是真正的内存泄漏,整个虚拟内存使用持续增长直到系统内存不足。

程序指令和数据靠占用内存来执行。他们经常会在使用过之后占用物理内存很长一段时间。闲置的代码和数据只会在现有剩余内存不能满足新的物理内存地址的请求的时候被移除出去。同样,因为虚拟内存地址空间是按照需要来映射到物理内存的这种方式,内存更看上去好像时时刻刻都在被完全使用。因此现在我们理解了一些机制并且知道问题是怎么出现的,那么那我们怎样来排错呢?第一件要理解的事情就是问题是否是因为物理内存不够所导致的过多的页面交换所引起的。然而,记住即使在有充足的有效内存的情况下过多的页面交换也有可能会发生-举个例子如果一个应用程序在泄漏内存。由于我们以前已经提到过,要有一个系统性能的一个基线来和任何你收集到的新的性能数据来对比是非常重要的。下面是一些关键的性能指标-这些描述都是直接从Windows Vista的性能监视器里面拿出来的:

计数器       

描述

Memory
  \ %Committed Bytes in Use

% Committed Bytes In Use 是 Memory\\Committed Bytes 与 Memory\\Commit Limit 之间的比值。(Commit Limit 是由物理内存和页面文件的大小而决定的。如果扩大了页面文件,该比例就会减小)。这个计数器只显示当前百分比;它不是一个平均值。

 如果这个值持续的超过80%的话,那么你的页面文件可能会太小了

Memory
  \ Available Bytes

Available Bytes 是指以字节表示的物理内存数量。此内存能立刻分配给一个进程或系统使用。

 如果这个值持续低于安装内存的5%,那么你应该要调查了。如果哦这个值持续低于安装内存的1%,这肯定是有问题的!

Memory
  \ Committed Bytes

Committed Byte 是指以字节表示的确认虚拟内存。确认内存磁盘页面文件上保留了空间的物理内存。每个物理磁盘上可以有一个或一个以上的页面文件。这个计数器只显示上一回观察到的值;它不是一个平均值。

 请留意这个值的发展趋势-如果这个值是持续的增加而不是呈水平状态,你应该要调查了。

Memory
  \ Pages / sec

Pages/sec 是指为解决硬页错误从磁盘读取或写入磁盘的速度。这个计数器是可以显示导致系统范围延缓类型错误的主要指示器。它是 Memory\\Pages Input/sec 和 Memory\\Pages Output/sec 的总和。是用页数计算的,以便在不用做转换的情况下就可以同其他页计数如: Memory\\Page Faults/sec 做比较,这个值包括为满足错误而在文件系统缓存(通常由应用程序请求)的非缓存映射内存文件中检索的页。

这个将依赖于这个页文件存放的磁盘速度。如果在一个慢的磁盘上面一直都超过每秒40或者在一个快的磁盘上面一直都超过每秒300的话,你应该要调查了。

Memory
  \ Pages Input / sec

Pages Input/sec 是从磁盘取读页面以解析硬页面错误的速度。它显示读取操作的数量,它并不考虑每个操作的页面数量。当一个进程引用一个虚拟内存的页面,而此虚拟内存位于工作集以外或物理内存的其他位置,并且此页面必须从磁盘检索时,就会发生硬页面错误。当页面发生错误时,系统尝试将多个连续页面读入内存以充分利用取读操作的优点。 请比较
  Memory\\Pages Input/sec 的值和 
  Memory\\Page Reads/sec 的值以便决定每个取读操作读入内存的平均页面数量。

这个会有区别-基于磁盘硬件和整体系统性能。在一个慢的磁盘上面,如果这个值一直超过20你可能会遇到问题。一个更快的磁盘可以处理更多。

Memory
  \ Pool Nonpaged Bytes

Pool Nonpaged Bytes 指在非分页池中的字节数,非分页池是指系统内存(操作系统使用的物理内存)中可供对象(指那些在不处于使用时不可以写入磁盘上而且只要分派过就必须保留在物理内存中的对象)使用的一个区域。Memory\\Pool
  Nonpaged Bytes 的计数方式与 Process\\Pool Nonpaged Bytes 的计数方式不同,因此可能不等于 Pool Nonpaged Bytes\\_Total。 这个计数器仅显示上一次观察的值;而不是一个平均值。

如果非分页池一直跑在超过80%,在一个连续的基础上,你可能会遇到非分页池用完的问题(事件ID2019)

Memory
  \ Pool Paged Bytes

Pool Paged Bytes 指在分页池中的字节数,分页池是系统内存(操作系统使用的物理内存)中可供对象(在不处于使用时可以写入磁盘的)使用的一个区域。Memory\\Pool Paged Bytes 的计数方式与 Process\\Pool Paged Bytes 的方式不同,因此可能不等于 Process\\Pool Paged Bytes\\_Total。这个计数器仅显示上一次观察的值;而不是一个平均值。

分页池是一个比非分页池更大的资源-然而,如果这个值一直都超过70%最大配置的池大小,你可能会有分页池用完的风险(事件ID 2020).看我们的文章“池资源的理解”了解详细内容,包括如何找到你当前最大的分页和非分页池的大小是多少。

Process
  (_Total) \ Private Bytes

Private Bytes 指这个处理不能与其他处理共享的、已分配的当前字节数。

近似于内存的Committed Bytes计数器,留意这个值的发展趋势。一个持续增长的值可能意味着内存泄漏。

LogicalDisk
  (pagefile drive) \ % idle time

% Idle Time 汇报在实例间隔时磁盘闲置时间的百分比。

如果装有页文件的驱动器的闲置时间小于50%的话,你可能有高磁盘I/O的问题。

LogicalDisk
  (pagefile drive) \ Split I/O / sec

Split IO/Sec 汇报磁盘上的 I/O 分割成多个 I/O 的速率。一个分割的 I/O 可能是由于请求的数据太大不能放进一个单一的 I/O 中或者磁盘碎片化而引起的。

与分割的I/O有关的问题依赖于磁盘分区类型和配置

因此,如果页文件显示了一个高使用率,这个页文件可能太小了。简单来说,如果装有页文件的磁盘过分的繁忙,整体系统性能可能会受到影响。由应用程序导致的内存泄漏以多种方式表现出来-你可能会得到一个说明系统缺少虚拟内存的消息。一个应用程序里面的内存泄漏将会显示为上面列出来的一个的Private Bytes计数器值的不断增加。一个进程的内存泄漏可能会导致过多的页面交换因为其他进程所使用的内存会被交换到页面文件。

现在你已经收到了你的数据并且定位这是什么问题了,在这种服务器缺少物理内存的案例里面,你既可以添加更多的内存(如果系统硬件和你正在运行的操作系统的版本都支持更多的内存)。你也可能会选择把一部分的负载减荷到其他的系统。然而,如果你的数据没有说明这么多的物理内存是一个问题,接下来是基于你收集的数据来看一看其他可能会遇到问题的组件。

如果内存看上去并不是一个问题的话,接下来我们不得不去定位这个具体的原因。在终端服务特定的环境里,随着越来越多的应用程序被加入到终端服务器的环境里面来,各种各样进程对资源要求的增加。在一些案例里面,你可能能够缩小问题到具体的进程。在这些情况下,两件事情中的一件有可能需要去做-你需要给机器添加更多的内存,或者进程本身就有问题需要注意。这里的关键是要理解这个进程到底在做什么。如果进程的虚拟内存稳定的上升并且之后呈水平状态,接下来增加页文件的大小可能是减轻问题所最需要做的了。如果内存仍然不够的话,然后你将会注意到增加的页面交换可能会导致系统性能的问题。然而,这里的关键是进程没有无限制的消耗虚拟内存-它是保持在一个固定的值。

在另一方面,如果应用程序消耗内存并且没有保持在一个水平状态,接下来应用程序就有可能正在泄漏内存。在一个内存泄漏的场景,应用程序保留并消耗内存资源,但是当不再需要的时候从来都不释放内存。取决于这个泄漏有多严重,虚拟内存可能会在几周、几天、几个小时或者甚至几分钟内被用完(在大多数极端的情况下)!看见一个缓慢的泄漏是更加常见的,这是可以用性能监视器日志来识别出来的。

另外一个可以导致性能降低的场景是发生在页文件本身碎片非常的多的时候。这会发生在当页文件放置在一个已经被其他应用程序频繁使用过的磁盘上面的时候。在这些案例中,磁盘本身是有很多碎片的。对磁盘的碎片整理应该是可以缓解一些这样的问题的,然而自系统内置的磁盘碎片整理程序不会对页文件进行碎片整理,你可能想会考虑把页文件临时移动到另外一个驱动器,在有碎片的磁盘上面设置页文件为0MB。重启系统来启用其他的页文件并且完成在原来驱动器上面碎片整理。一旦碎片整理完成了,你可能要在原驱动器上面重新设置页文件到必要的值,把临时驱动器上面的页文件清空并再次的重启系统。这篇文章的讨论就到此为止。在我们下篇文章中,将继续看一看内存使用问题的排错。

 

本文转译自AskPerf的博客文章, 原文链接如下:

http://blogs.technet.com/b/askperf/archive/2008/01/25/an-overview-of-troubleshooting-memory-issues.aspx