测量C ++中的并发代码使用的内存消耗

时间:2018-06-19 19:30:31

标签: c++ concurrency linked-list memory-consumption

我正在用C ++实现 FineList LazyList 类。上面的两个并发链接列表都已在《 多处理器编程的艺术》一书中用Java实现。我想衡量每个算法在整个执行过程中消耗的内存量。我不确定该怎么做。我可以跟踪两种算法中每个线程在计数器中调用“ ”的次数,并将其用作度量标准。同样,每当线程调用“ 删除”时,我都会减少计数器的数量。这是衡量内存消耗的公平标准吗?问题在于,FineList算法具有基于锁的性质,一旦将其从链表中删除,我就可以立即“删除”该节点。但LazyList算法不是这种情况,因为它具有无锁方法。还有其他方法可以测量内存消耗吗?或者上述方法对两种算法都公平吗?

2 个答案:

答案 0 :(得分:1)

如果您保留了newdelete调用的有序日志(包括请求的大小),并且您确定您感兴趣的代码仅使用new和{{1 }}(而不是其他分配例程),您可以在任何时间点通过释放已分配的内存上的剩余内存的运行计数来确定理论的内存消耗。您也许可以通过重载全局delete以及删除来生成这样的日志。

由于以下几个因素,该数字仅为理论

  1. 分配器会增加一定的开销,因此分配的实际内存通常将大于分配的对象大小的总和。这种开销包括碎片,因为某些未分配的内存在技术上可能是免费的,但并非真正可用。
  2. 分配器可能不会将任何内存返回给操作系统,或者可能会以无法预测的方式将其返回给操作系统。因此,如果就操作系统而言(相对于运行时分配器而言)测量“已分配的内存”,那么您将遇到一个更棘手的问题,这高度依赖于分配器。
  3. 尤其是在多线程方案中,将来的分配不一定使用所有释放的内存。对于线程感知的分配器,这种情况的一个特殊情况是使用线程本地分配缓冲区:一个线程上释放的内存可能无法立即在另一个线程上使用,直到达到某个阈值,以便分配可以在线程间移动。如果线程之间分配和释放的节点之间存在差异,这可能与您的情况有关。
  4. 要确定已分配的内存量甚至要定义该术语,整个过程都是很复杂的。例如,对于较大的分配,OS可能会向您返回实际上不存在于RAM中的一块内存,并且在您访问它时只能对其进行分页。因此,如果您不访问分配的所有内容,分配器报告的数字实际上可能会被高估。

那只是在刮擦表面。

答案 1 :(得分:0)

C ++允许您提供自己的operator new和匹配的operator delete。这对于此类测量任务很有用。您甚至可以使用它来计算根据分配策略使用的内存,例如查看将分配舍入到16字节的倍数时算法需要多少内存。

此方法的最大好处是您无需触摸算法本身的代码。您可以使用自己的分配器记账。

请记住,如果您确实需要new,那么无锁编程的想法可能会过于乐观。在C ++中,不能保证new是无锁的。而且由于C ++允许您在一个线程中new和在另一线程delete中进行内存,所以需要一些跨线程同步。