2

我正在尝试在 C++ 中使用更快的内存分配器。由于许可/成本,我无法使用 Hoard。我在单线程设置中使用 NEDMalloc 并获得了出色的性能,但我想知道是否应该切换到其他东西——据我了解,NEDMalloc 只是基于 C 的 malloc() 和 free() 的替代品,不是基于 C++ 的 new & delete 运算符(我广泛使用)。

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

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

所以我遇到了这种奇怪的情况,我使用 new 分配锁,使用 nedmalloc 分配其他所有内容。但是当我分配大量内存时,我遇到了分配错误(当我切换到 malloc 而不是 nedmalloc 时消失了〜但性能很糟糕)。我的猜测是,这是由于内存碎片以及 nedmalloc 和 new 无法并排放置 nice 造成的。

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

4

4 回答 4

4

谷歌的malloc 替换非常快,默认线程安全且易于使用。只需将其链接到您的应用程序中,它将替换行为或malloc/freenew/ delete。这使得重新分析您的应用程序以验证新的分配器实际上加速了事情变得特别容易。

于 2010-06-14T16:55:02.267 回答
2

您可以重载全局运算符newdelete调用您正在使用malloc的新版本。free这应该会让事情变得更好,但如果这还没有发生,我会感到惊讶。

至于创建互斥体,请使用placement new——这是手动调用构造函数的方式。一个静态数组char将通过缓冲区来完成。例如,全局变量:

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

然后初始化m指针:

m=new(buf) Mutex;

(如果需要,您还可以对齐指针等,并重命名变量等。)

可能值得注意的一件事是,如果Mutex构造函数自己分配更多内存,那么这可能是一个问题。这不太可能,但可能。(对于这种可能很少见的情况,跨平台互斥包装器的临时实现通常没有问题,它不进行任何分配 - 或者,尽管最终会变得一团糟,只需直接使用#ifdef和使用平台类型。无论哪种情况,都不需要太多代码,任何对相关系统有经验的人都可以在很短的时间内创建相关代码,没有错误。)

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

于 2010-06-14T17:00:17.140 回答
1

您是否分析并验证了实际内存分配是一个足够重要的问题,替换分配器提供了有用的收益?

NEDMalloc 线程安全吗?

通常,默认的 c++ new/delete 运算符将在调用构造函数/析构函数之前/之后在后台使用 malloc 和 free 来进行实际的内存分配。如果它们不在您的特定情况下,您可以覆盖全局 new 和 delete 运算符来调用您希望的任何分配实现。这需要注意确保始终使用相同的分配器分配/释放内存(尤其是在处理库时)。

于 2010-06-14T16:53:51.767 回答
1

好吧,通常 C++newdelete运算符在内部调用普通 C 库函数mallocfree(加上一些额外的魔法,如调用 ctors 和 dtors),因此为这些函数提供自定义实现可能就足够了(这在嵌入式 C++ 开发中并不罕见,但需要一些链接器级工作)。你的目标是什么系统和编译器?

于 2010-06-14T16:57:08.993 回答