【问题标题】:How to explain drastic jump in memory allocation latency?如何解释内存分配延迟的急剧跳跃?
【发布时间】:2013-12-15 03:28:33
【问题描述】:

配备 8GB RAM 的英特尔赛扬 847。 (C/C++ 不是 .NET)

这是在 Windows EC7 上运行的唯一线程/函数。

它只是循环分配 1MB 的内存,1000 次。

但是,在循环的第 122 次迭代之后,分配所需的时间从大约 47 微秒增加到 327 微秒。

有哪些可能的原因可以向我的老板解释这一点?

while ( i < ITERATIONS )
{
QueryPerformanceCounter(&li);
start = double(li.QuadPart) / PCFreq;

// allocate 1MB
ptr = new char [1048576]; // 1 byte * 1048576 = 1 MB

QueryPerformanceCounter(&li);
stop = double(li.QuadPart) / PCFreq;

delayAlloc[i] = stop - start;

}

编辑

为了确定,我又执行了 3 次测试,每次的结果都与此非常相似:

【问题讨论】:

  • 问:这是一个物理设备(而不是模拟器),对吗?问:您的设备上有多少物理 RAM?问:您是在 .Net 还是 C/C++ 中编码?问:您能否运行 WinCE 等效的 TaskMgr 或性能监视器? DevHealth 呢?您需要获得更多信息才能希望回答这个问题...
  • 对你老板的一个解释是,即使在这么简单的一段代码中,你也设法造成了内存泄漏?
  • 您可以尝试使用调试器在第 1 次和第 123 次迭代中单步执行新代码,以查看它采用的代码路径。您使用的是哪个编译器?这将告诉我们它是哪个内存分配器。
  • 您没有触及分配的内存:首先要找出的是:来自new 的内存是否正在提交(分配的物理内存帧?)或者它只是未填充的虚拟内存内存?
  • @P.S. :根据分配器和 Windows 本身管理内存块(页面)的方式,如果已经分配了相当大的块(如 @Hari Mahadevan 解释的),则可能会间接获取新块。将其视为容器结构,分配条目越多,必须完成的工作就越多才能找到内存中的空闲间隙。还有硬件限制,阅读有关 CPU 的 MMU&TLB 的信息,它们具有有限数量的(缓存)条目,并且在通过缓存拉内存页(+条目)时具有一定的开销。要获得有意义的结果,请memset() 块,以“弄脏”页面。

标签: c++ c windows memory windows-ce


【解决方案1】:

我能想到的一个可能原因是程序堆在某个阶段被完全消耗,然后内存管理器必须通过循环和跳转来通过将一些已经分配的块交换到辅助存储来管理进一步的分配请求。很大程度上取决于您有多少已安装的 RAM 以及有多少可用于您的程序。

如果将分配大小设置为 512K 而不是 1MB,会发生什么情况?是否会发生同样的事情,但在第 200 次迭代时?你可以增加可用的 RAM 并尝试吗? (我不知道 Windows EC7 是什么,但我的回答基于我的 WinDesktop 经验)。

【讨论】:

  • 这也是我的想法,但不确定,我会尝试更改大小以查看它是否在 200 次迭代左右保持一致...谢谢。
【解决方案2】:

让我们简化您的代码并删除计时的东西。

while ( i < ITERATIONS )
{
    // allocate 1MB
    ptr = new char [1048576]; // 1 byte * 1048576 = 1 MB
}

系统正在为您分配 1Mb 并返回地址。然后您要求另一个地址,并将新地址存储在您保存先前地址的同一变量中。

new 返回一个指针,而指针实际上是只是分配的地址。它不是特殊的电子钥匙,也不是有作用域的对象,它只是内存中分配开始位置的数值。

当你不再需要内存时,告诉分配器是你的责任。无论您是否存储它,它都无法知道您如何处理该地址数据。

while ( i < ITERATIONS )
{
    // allocate 1MB
    ptr = new char [1048576]; // 1 byte * 1048576 = 1 MB

    delete [] ptr;
}

如果您不这样做,分配的内存将永远返回到池中,直到您的应用程序终止。

这意味着您的应用程序的内存占用量正在增长。在普通 Windows 下,这可能不是问题,但您在 Windows 的嵌入式风格下运行,其中 one Mb 的内存已经是相当大的数量。前 122Mb 可能已预先保留给您的应用程序。但是一旦你分配了你的应用程序开始使用的所有堆,分配器必须调整它的堆大小才能为你提供额外的分配,并且由于这是嵌入式 Windows,所以调整大小是悲观的。

【讨论】:

    【解决方案3】:

    您的代码根本没有使用 RAM,在您实际访问数组之前不会发生这种情况。所以唯一需要做的工作就是在虚拟内存地址空间中找到一个漏洞并提交它。找洞不能这么突然跳。提交可以,有一个便宜和昂贵的版本。便宜的是页面文件中的空间已经可用。代价高昂的是需要通过增长分页文件来创建它。

    通过运行程序两次来验证这一点。第二次跳转应该稍后发生或根本不发生。

    【讨论】:

    • 好吧,我又跑了,你凭什么相信第二次,应该以后再跳?
    • 幽默我们,运行两次测试。
    猜你喜欢
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多