我正在用 C++ 实现FineList和LazyList类。上述两个并发链表都在《多处理器编程的艺术》一书中用 Java 实现。我想测量每个算法在整个执行过程中消耗的内存量。我不确定我该怎么做。我可以在两种算法中跟踪每个线程在计数器中调用“ new ”的次数,并将其用作衡量标准。同样,每当一个线程调用“删除“,我会减少计数器。这是衡量内存消耗的公平标准吗?问题是 FineList 算法允许我在节点从链表中删除后立即“删除”,因为它是基于锁的性质。但在 LazyList 算法中并非如此,因为它具有无锁方法。有没有其他方法可以测量内存消耗,或者上述方法对两种算法都公平吗?
问问题
160 次
2 回答
1
new
如果您保留和调用的有序日志delete
(包括请求的大小)并且您确定您感兴趣的代码仅使用new
而不是其他分配例程,您可以在任何时间点delete
或多或少地确定理论内存消耗通过保持对分配的内存超出释放的内存的运行记录。您也许可以通过重载全局operator new(size_t)
和删除来生成这样的日志。
由于以下几个因素,这个数字只是理论上的:
- 分配器会增加一定的开销,因此实际分配的内存通常会大于分配的对象大小的总和。这种开销包括碎片,因为一些未分配的内存在技术上可能是免费的,但实际上并不可用。
- 分配器可能不会将任何内存返回给操作系统,或者它们可能会以不可预测的方式返回它。因此,如果就操作系统而言(相对于运行时分配器而言),您正在测量“分配的内存”,那么您将遇到一个更难的问题,并且这是高度依赖于分配器的。
- 尤其是在多线程场景中,并非所有释放的内存都必须由未来的分配使用。线程感知分配器的一个特定情况是使用线程本地分配缓冲区:在一个线程上释放的内存可能无法立即在另一个线程上使用,直到达到某个阈值,分配可以跨线程移动。如果线程之间分配和释放的节点存在差异,这可能与您的方案相关。
- 在确定分配了多少内存时,有一个复杂的层次——甚至是定义该术语。例如,对于一个大的分配,操作系统可能会返回一块实际上并不存在于 RAM 中的内存,并且只有在你访问它时才对其进行分页。因此,如果您不访问您分配的所有内容,则分配器报告的数字实际上可能被高估了。
这只是表面问题。
于 2018-06-19T21:39:57.480 回答
0
C++ 允许您提供自己的operator new
和匹配的operator delete
. 这对于此类测量任务很有用。您甚至可以使用它来计算用作分配策略函数的内存,例如,当将分配舍入到 16 字节的倍数时,查看您的算法需要多少内存。
这种方法的最大好处是您不需要接触算法本身的代码。您可以使用自己的分配器的簿记。
请注意,如果您确实需要,无锁编程的想法可能过于乐观new
。C++ 中没有任何保证new
是无锁的。由于 C++ 允许您new
在一个线程中进行内存,而delete
在另一个线程中进行内存,因此需要一些跨线程同步。
于 2018-06-20T10:26:25.107 回答