C# 简单应用程序会产生大量页面错误。为什么?

标签 c# windows c#-3.0

拥有将文本数据导入 SQL 的简单 C# 控制台应用程序。

它占用大约 300K 的内存和 80% 的 CPU。随时有 2Gb RAM 可用,但页面错误显示 500K。

应用程序是 32 位的,操作系统是 W2000 或 XP 32 位和 .NET 3.5

任何人都可以解释可能是什么问题,我该如何进一步调查?

编辑:我现在确定页面错误与磁盘 I/O(读取)有关。我注释掉了 SQL 部分,纯磁盘读取单独生成了那么高的数字。

EDIT2:平均每秒有 200 个硬故障和 4000 个软故障。

不知道W2008会不会出现同样的情况

最佳答案

首先,您如何衡量应用使用的内存?如果您正在查看“工作集”,那只是驻留在物理内存中的部分。您还应该查看进程占用的实际虚拟内存所在的“VM 大小”(或“提交大小”)。

如果 Windows 内核平衡集管理器认为您的应用程序处于非事件状态,或者应该留下来为其他进程提供更多功能,它可以决定减少工作集大小。如果工作集大小小于您的应用程序实际需要处理的大小,您很容易看到大量页面错误,因为它只是成为平衡集管理器和应用程序之间的竞争。通常平衡集管理器监视内存使用情况,并且还可以决定相应地增加工作集大小。但是,这可能会在某些情况下被阻止,例如低物理空闲内存、高 I/O(物理内存上的缓存压力)、低进程优先级、应用程序的后台/前台状态等。

这可能只是 .NET 垃圾收集器的行为,因为大量的小内存块在很短的时间内被分配和处理,从而对内存分配和释放造成压力。 “VM 大小”可能保持大约相同的大小,但在幕后它可能会连续分配/释放内存,从而导致连续页面错误。

还知道,进程正在使用的 DLL 也包含在进程统计信息中。不是您的应用程序,而是您正在使用的 COM 或 .NET DLL 之一也可能导致此行为。您可以通过更改应用程序的行为(例如删除数据库访问代码并只留下对象分配代码)来推断真正的罪魁祸首,以查看哪个组件实际上导致了抖动。

编辑:关于您关于 GC 对内存抖动的影响的问题:The CLR actually grows the heap dynamically and gives the memory back to the OS as needed .这不会同步发生。 GC 在后台运行并释放大块内存以防止影响应用程序性能。假设您正在分配许多小对象并几乎立即释放它们。这会导致许多引用在释放之前在内存中停留片刻。很容易想象,这就像垃圾收集器和内存分配代码之间的一场正面交锋。当 GC 最终 catch 时,必须从“新内存”而不是旧内存中满足所需的新内存,因为旧内存尚未释放。由于我们正在处理的实际内存保持不变,平衡集管理器可能不会考虑为我们的进程提供更多内存,因为我们处于边缘,始终处于相同的物理内存大小但不断需要“新分配的内存”而不是“更多内存”,因此页面错误。

关于C# 简单应用程序会产生大量页面错误。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5066708/

相关文章:

c# - 为 C# 设置枚举

c# - 将 BitmapImage 转换为 Image.Source

c# - 使用 $expand 时的 Web API OData 媒体类型格式化程序

c# - 将字符串中 '=' 的所有实例替换为 '=='

c# - 释放在 WPF Application.OnStartUp() : Which thread owns it? 中创建的命名互斥体

windows - 在 Windows 上使用 node.js 解压文件

c# - GlobalConfiguration.Configure(WebApiConfig.Register) 挂起

c++ - GetTokenInformation 在 Windows Server 2003 上失败(错误 998)但在 2008 上有效

c# - 延迟执行和急切评估

c# - 可以改进检查类型然后进行转换的代码吗?