2010-06-14 84 views
2

我想在C++中使用更快的内存分配器。由于许可/成本,我无法使用Hoard。我在单线程设置中使用了NEDMalloc并获得了很好的性能,但是我想知道是否应该切换到别的东西 - 据我了解,NEDMalloc仅仅是基于C的malloc()的替代品()& free(), 不是基于C++的新的&删除操作符(我广泛使用)。Boost :: Mutex&Malloc

问题是我现在需要线程安全,所以我试图malloc一个引用计数的对象(以防止过度复制),但其中还包含一个互斥量指针。这样,如果你要删除最后一个副本,你首先需要锁定指针,然后释放该对象,最后解锁&免费的互斥锁。

但是,使用malloc创建boost :: mutex似乎不可能,因为我无法将私有对象初始化为直接调用构造函数ist verboten。

所以我留下了这种奇怪的情况,我用新来分配锁和nedmalloc分配一切。但是当我分配大量内存时,我遇到了分配错误(当我切换到malloc而不是nedmalloc时,它会消失 - 但性能很糟糕)。我的猜测是,这是由于内存中的碎片化以及nedmalloc和new的兼容性不佳而导致的。

必须有更好的解决方案。你会建议什么?

+1

你可以使用placement new直接调用构造函数。 – 2010-06-14 19:52:37

回答

4

谷歌的malloc replacement是相当快的,默认线程安全,易于使用。只需将其链接到您的应用程序中即可取代该行为或malloc/freenew/delete。这使得重新配置应用程序非常容易,以验证新的分配器实际上是在加快速度。

1

您是否分析过并验证过实际的内存分配是一个足够严重的问题:替换分配器会提供有用的增益?

NEDMalloc线程安全吗?

通常,默认的C++ new/delete操作符会在调用构造函数/析构函数之前/之后使用malloc和free来实现内存分配。如果它们不符合你的特定情况,你可以重写全局的new和delete操作符来调用你想要的任何分配实现。这需要注意确保内存总是使用相同的分配器分配/释放(特别是在处理库时)。

+0

我想知道这是什么实际上导致问题 - 混合malloc&nedmalloc。我会首先尝试tcmalloc,因为它透明地处理新/删除操作,但是随后我会回过头来,放置新的位置和上面的缓冲区解决方案。 – 2010-06-14 17:39:06

1

嘛,通常是C++ newdelete运营商内部调用普通C库函数mallocfree(加上一些额外的魔法就像调用构建函数和dtors),因此提供了一个自定义实现这些功能可能不够(这不是罕见嵌入式C++开发,但需要一些链接器级别的工作)。你的目标是什么系统和什么编译器?

+0

我定位: GCC 4.3 - Ubuntu的10.04 GCC 4.5 - 红帽5.5 MS VS 2005,2008年,与2010年XP SP2和3,最终的Windows 7 因此,我本来想用升压+的东西,我(像nedmalloc一样)尽可能便携。 – 2010-06-14 17:36:40

+0

只需要跟进 - 爱tcmalloc,直到最近与gcc 4.5,它不工作,但都只是补丁和事情现在唱歌。我唯一没有工作的版本是VS 2010中的64位原生Win 7上的32位版本 - 但这可能不是tcmalloc的错。 __Update:__从来没有想过CUDA 3.2 Beta在我没有怀疑的方面表现不佳。 Tcmalloc从来没有责怪。 – 2010-09-17 00:16:37

2

您可以使全球运营商newdelete超载,以调用您正在使用的新版本mallocfree。这应该让事情在一起发挥得更好,但如果这种情况还没有发生,我会感到惊讶。

至于创建互斥量,使用放置新 - 这是如何手动调用构造函数。一个静态数组char将通过缓冲区来完成。例如,全局:

static char buf[sizeof(Mutex)]; 
static Mutex *m=0; 

然后初始化m指针:

m=new(buf) Mutex; 

(您也可以将指针,等等,如果你需要,并重新命名变量等等)

可能值得注意的一件事是,如果Mutex构造函数本身执行更多的内存分配,那么这可能是一个问题。这不太可能,但可能。 (对于这种可能性很小的情况,跨平台互斥包装器的临时实现通常没有问题,它不会进行任何分配 - 或者,尽管最终会导致混乱,只需使用#ifdef并直接使用平台类型,无论是哪种情况,代码都不多,并且有关系统的任何人都可以在很短的时间内创建相关代码,无bug。)

正确清理以这种方式创建的对象可能很困难,所以我建议不要打扰(不,认真)。当你使用它来实现内存管理器时,让这些东西泄漏是完全可以的;没有一点让它疯狂。 (如果你正在使用一个有退出进程概念的系统,那么操作系统几乎可以保证为你清理底层互斥锁。)

+0

但是这有副作用(它可能是一个想要的副作用),你必须为你想用自定义分配器管理的每个类提供一个新的重载。 – Wizard79 2010-06-14 17:06:05

+1

没有自定义分配器;放置新标准是正常的,全球运营商的新增和删除操作正在被覆盖(如果甚至有必要的话)。我确实想到了一个问题,并会相应地编辑答案。 – 2010-06-14 17:15:54

+0

我不能标出两个解决方案。我会在tcmalloc之后尝试。谢谢! – 2010-06-14 17:40:18

相关问题