有简单的C#控制台应用程序,它将文本数据导入SQL.
内存大约需要300K,CPU需要80%.可以随时使用2Gb RAM,但Page Fault显示500K.
该应用程序是32位,操作系统是W2000或XP 32位和.NET 3.5
任何人都可以解释可能存在的问题,我该如何进一步调查?
编辑:我现在确定页面错误与磁盘I/O(读取)有关.我注释掉SQL部分,纯磁盘读取仅生成高数字.
EDIT2:平均有200个硬故障/秒和4000个软故障/秒.
我想知道W2008上会出现同样的情况
首先,您如何衡量应用程序使用的内存?如果您正在查看"工作集",那只是驻留在物理内存中的部分.您还应该查看"VM大小"(或"提交大小"),其中您的进程占用了实际的虚拟内存.
如果Windows内核Balance Set Manager认为您的应用程序处于非活动状态,或者应该留下来为其他进程提供更多功能,则可以决定减少工作集大小.如果工作集大小小于应用程序实际需要处理的大小,则可以很容易地看到很多页面错误,因为它只会成为平衡集管理器和应用程序之间的竞争.通常,余额集管理器监视内存使用情况,并且还可以决定相应地增加工作集大小.但是,在某些情况下可能会出现这种情况,例如低物理空闲内存,高I/O(物理内存缓存压力),低进程优先级,应用程序的后台/前台状态等.
它可能只是.NET垃圾收集器的行为,因为大量的小内存块在很短的时间内被分配和处理,从而对内存分配和释放造成压力."VM Size"可以保持大致相同的大小,但在幕后可能会不断分配/释放内存,从而导致连续的页面错误.
还要知道进程正在使用的DLL也会占进程统计信息.不是您的应用程序,而是您正在使用的COM或.NET DLL之一也可能导致此行为.您可以通过更改应用程序的行为(例如,删除数据库访问代码并仅保留对象分配代码)来推断实际的罪魁祸首,以查看哪个组件实际上正在导致颠簸.
编辑:关于GC对内存抖动的影响的问题:CLR实际上动态增长堆并根据需要将内存返回给操作系统.这不会同步发生.GC在幕后运行并释放大块内存,以防止阻碍应用程序性能.假设您正在分配许多小对象并几乎立即释放它们.这导致许多引用在释放之前在内存中停留片刻.很容易想象它变得像垃圾收集器和内存分配代码之间的头对头竞争.当GC最终赶上时,所需的新内存必须从"新内存"中得到满足,而不是旧内存,因为旧内存尚未释放.由于我们正在处理的实际内存保持不变,因此平衡集管理器可能不会考虑为我们的进程提供更多内存,因为我们处于边缘,总是在相同的物理内存大小但是经常需要"新分配的内存"而不是"更多"内存",因此页面错误.