在Windows上打开文件的内存开销是什么?



tl; dr

打开文件在现代Windows系统上会有多少内存?某些应用程序负载将需要打开"很多"文件。Windows非常有能力打开"很多"文件,但是保持单个文件打开的负载是什么,以便可以决定何时"很多"是"太多"?

背景

用于在32位进程中的大型数据集(100s Mb〜几个GB)的顺序处理,我们需要提出一个缓冲区,该缓冲区将其内容存储在磁盘上而不是在内存中。

我们已经充实了一个小课,没有太多问题(将CreateFileFILE_ATTRIBUTE_TEMPORARYFILE_FLAG_DELETE_ON_CLOSE一起使用)。

问题是,这些缓冲区的使用方式是,每个缓冲区(每个临时文件)可能会从几个字节中存储到最多几个GB数据,我们希望将缓冲区类本身保持为最小和一般。

用例范围从100个缓冲区,每个缓冲区〜100MB到100.000秒的缓冲区,每个缓冲区只有几个字节。(是的,重要的是,每个缓冲区都有自己的文件。)

在缓冲区类中包含一个缓冲区阈值似乎很自然,该类别仅在实际存储字节时才开始创建和使用临时的磁盘文件,而不是(内存)创建 引用临时文件使用的(内存)开销 - 在过程以及物理机器内存上的加载。

问题

在字节中,打开(临时)文件在现代Windows系统上是否有多少内存?

  • FILE_ATTRIBUTE_TEMPORARYFILE_FLAG_DELETE_ON_CLOSE一起使用CreateFile
  • (32位)进程的虚拟地址空间的字节打开文件
  • 机器上物理内存的字节(包括任何内核数据架构)

也就是说,当您从将数据存储在文件中而不是内存?

时,当您开始看到净主机内存增益(既包括在程序内和物理上)时,阈值是什么?

注意:

提到的打开文件限制的注释不适用于CreateFile,仅适用于MS CRT文件API。(通过CreateFile打开10.00个文件在我的系统上根本没有问题 - 这是否是一个完全不同的问题,而不是这个问题的一部分。

内存映射文件:完全不适合在32位进程中处理GB数据,因为您无法可靠地将如此大的数据集映射到32位进程的正常2GB地址范围。完全对我的问题毫无用处,并且完全没有与实际问题有关。平原文件对于背景问题就可以了。

看http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/29/3283844.44.aspx-告诉我HANDLE本身在64位的系统上占16个字节,但是那是 Just 手柄。

查看了stxxl及其文档,但此lib既不适合我的任务,也没有发现在开始使用之前使用文件。


有用的评论摘要:

雷蒙德写道:"答案会根据安装了什么防病毒软件而有所不同,因此唯一知道的方法是在生产配置上进行测试。"

QWM写道:"我会更关心CPU开销。无论如何,回答您的问题的最佳方法是测试它。我只能说仅_FILE_OBJECT的大小(包括_OBJECT_HEADER)是〜300B它的字段是其他相关结构的指针。"

damon写道:"一个正确的答案是:10个字节(在我的Windows 7机器上)。由于没有其他人值得实际尝试,所以我做到了(MEMORYSTATUSEX::ullAvailVirtual的差异在100K呼叫中进行了测量,没有其他运行)。问我为什么不是8或16个字节,我不知道。大约需要17秒的内核时间,流程在退出时开放了100,030个手柄。在运行过程中,私人工作设置在运行期间增加了412K,而全局可用的VM则下降了到1m,大约60%的内存开销位于内核内。(...)"

"更令人惊叹的是大量的内核时间(CPU时间忙,而不是等待磁盘!),CreateFile显然消耗了。17秒的17秒钟100k呼叫沸腾到约450,000个周期,以打开一个手柄。这台机器。与此相比,仅10个字节的虚拟内存都可以忽略不计。"

我现在进行了一些测量:

  • 我设置了带有2G的RAM磁盘,以免弄乱我的普通NTFS文件表。
  • 我在循环中创建了1M文件(1,000,000),并通过Perfmon检查了各种系统性能指标。

创建一个临时文件的调用(我将其保留直到最后)看起来像这样:

HANDLE CreateNewTempFile(LPCTSTR filePath) {
    return ::CreateFile(
        filePath, 
        GENERIC_READ | GENERIC_WRITE, // reading and writing
        FILE_SHARE_READ, // Note: FILE_FLAG_DELETE_ON_CLOSE will also block readers, unless they specify FILE_SHARE_DELETE 
        /*Security:*/NULL, 
        CREATE_NEW, // only create if does not exist
        FILE_ATTRIBUTE_TEMPORARY | // optimize access for temporary file
        FILE_FLAG_DELETE_ON_CLOSE, // delete once the last handle has been closed
        NULL);
}

结果是:

  • 再次删除了所有临时文件,RAM磁盘的使用如下:
    • 总计2060 m字节
    • 使用1063 m字节
    • 免费997 m字节
  • 比较启动和结束值(与介于两者之间的几个样本)我总结了以下每个打开的平均内存消耗(temp)文件
    • 内存/可用字节 - 大约4K字节每个打开文件降低(此计数器上的抖动:显然,因为此测试持续了10分钟
    • 内存/池paged字节 - 大约每个打开文件3K字节
    • 内存/池非页面字节 - 大约每个打开文件2,2k字节
  • 有趣的是, Process 内存负载并没有以任何重要的方式增加(按过程/工作集跟踪)。

请注意,我还完全没有使用页面文件(因为我希望这台机器具有16GB的RAM,并且在最低点我仍然可以免费使用〜4GB)。

最新更新