如何在C ++中有效地管理内存/时间?

时间:2013-12-24 10:47:57

标签: java c++ memory garbage-collection

案例:

我用Java编写了一个minimax算法,然后我用C ++移植了代码,保留了相同的类和方法。然后我通过将delete函数放在析构函数中(如果可能的话)来修改C ++代码直到所有内存泄漏都得到修复。当所有泄漏都得到修复后,我在一个井字游戏中测试了算法,然后在C ++中将代码移植到相同的位置。我确信C ++版本的性能会更高,但我很惊讶看到C ++版本在125秒内解决了100个(非随机)游戏实例,而Java版本在30秒内解决了它们! 然后,使用系统监视器我检查了两个程序的内存使用情况:测试结束时的Java代码内存使用量增加了大约20%,而使用C ++版本时,内存仅增加了5%。

然后,在我看来,很明显这个delete策略是节省内存但是会导致时间性能下降,这不是我想要的,至少在这种情况下是这样。是否有另一个删除策略来更好地设计需要小运行时但允许高内存使用的软件?

2 个答案:

答案 0 :(得分:3)

malloc和delete必须做更多工作

  • 内存不是以多线程方式分配的
  • 内存不会在内存中连续分配,而是分配给可用内存区域。
  • delete在当前主题中执行。
  • 对于64位应用程序,您可能会发现内存对齐是16个字节而不是8个字节,从而导致每次分配更多填充。

C ++中可能的解决方案

  • 不要使用堆这么多,在堆栈上分配要比Java或C ++的堆快得多,并且它是多线程的。
  • 如果可能的话,一次分配对象块,例如一个对象数组是C ++中的一个分配,而不是Java中的N + 1。
  • 使用多线程分配器。 C ++支持多个分配器。
  • 使用竞技场分配模式。如果您有一个包含大量节点的大型数据结构,则可以一次分配N个节点的块,当您释放这些节点时,可以构建一个自由节点的链接列表。您需要使用节点本身执行此操作。在这种方法中,整个数据结构/竞技场立即被解除分配。

简而言之,如果你将Java代码直译为C ++,它可能会慢一点,因为它没有利用C ++允许的所有优化,但Java没有。

BTW Java 6+使用32位引用,最高可达32 GB内存。如果您构建一个64位C ++应用程序,请查看是否可以使用32位指针/引用/索引。

答案 1 :(得分:1)

如果你经常建造一棵树(有很多小树) 动态分配节点并将其拆除,你就是在 最有利的垃圾收集案例。你可能想要 使用Boehm收集器和C ++。 (IIRC,Boehm的基准, 旨在表明垃圾收集可以比快 手动分配,做一些非常类似的事情:构建 大树,然后撕下它们。)

或者,您可以查看某种内存池。 这不是C ++中的初学者技术,但事实并非如此 很难。或者,而不是删除节点,你放 将它们放到免费清单上,以便以后回收。 (分配时,你 首先查看免费列表,如果是,则只调用new 空的。)或两者结合起来。