当使用new或malloc分配内存时,分配器可能必须保护自己不被重新进入。我看到了两种方法:
- 一个大互斥。此解决方案很简单,但性能较差
- 为每个线程保留一个内存池。性能很高,但池的大小可能很难评估
我认为大多数分配器都使用第二种方法,但我找不到这方面的证据。
你知道哪个分配器使用哪个方法吗?这有什么标准吗?
Google perf工具提供了一个名为TCMalloc的分配器。这个分配器为每个线程使用一个内存池(="线程缓存系统")。文档显示了对glibc 2.3的性能改进度量。
自2.16以来,Glibc为每个线程使用一个内存池。
因此,现在没有更多的性能差异:
Fedora[我们]曾经在QEMU中使用tcmalloc一段时间。然后我们检查了性能再次发现glibc的原生malloc的delta基本上已经
还要注意,C++new
运算符调用libc
提供的malloc
函数(在大多数情况下为glibcmalloc)。
因此:
- 不,这种行为不规范
- 它仅在每个线程使用一个池(并且仅当)您使用glibc>=2.16时,否则您可以尝试使用TCMalloc进行编译
C++17开始指定线程应用程序中分配器的行为:
- std::pmr::unsynchronized_pool_resource不是线程安全的,不能从多个线程同时访问
- std::pmr::synchronized_pool_resource可以在没有外部同步的情况下从多个线程访问,并且可以具有特定于线程的池以降低同步成本。如果只从一个线程访问内存资源,那么非同步的_pool_resource会更有效率
我用intel parallel studio
(在windows下)进行的所有多线程程序分析,由于分配,总是显示锁定事件和内核时间。这意味着VS'08编译器的C++新版本主要使用互斥来保持内存一致性。
每次在我开发的软件中出现问题时,我都会尝试使用RIA习惯用法并删除动态/共享内存,或者如果内存只能由线程本身使用,则使用TLS分配器。