Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有效地分配许多短期的小对象_C++_Visual Studio 2008_Multithreading_Memory Management - Fatal编程技术网

C++ 有效地分配许多短期的小对象

C++ 有效地分配许多短期的小对象,c++,visual-studio-2008,multithreading,memory-management,C++,Visual Studio 2008,Multithreading,Memory Management,我有一个小类(32位系统上有16个字节),需要动态分配。在大多数情况下,任何给定实例的生命周期都非常短。某些实例也可以跨线程边界传递 在做了一些分析之后,我发现我的程序在分配和取消分配这些东西上花费的时间似乎比实际使用它们花费的时间要多,所以我想用更高效的东西来替换默认的new和delete 对于一个大的对象(db连接,实际上,构造它比分配它要昂贵),我已经在使用一个池系统,但是它包括一个用于存储“空闲”对象的列表,以及一个用于线程安全的互斥对象。在互斥体和列表之间,对于小对象,它的性能实际上比

我有一个小类(32位系统上有16个字节),需要动态分配。在大多数情况下,任何给定实例的生命周期都非常短。某些实例也可以跨线程边界传递

在做了一些分析之后,我发现我的程序在分配和取消分配这些东西上花费的时间似乎比实际使用它们花费的时间要多,所以我想用更高效的东西来替换默认的new和delete

对于一个大的对象(db连接,实际上,构造它比分配它要昂贵),我已经在使用一个池系统,但是它包括一个用于存储“空闲”对象的列表,以及一个用于线程安全的互斥对象。在互斥体和列表之间,对于小对象,它的性能实际上比基本的new/delete要差

我在Google上发现了许多小对象分配器,但它们似乎使用的是全局/静态池,而不是线程安全的方式,因此不适合我使用:(


对于这些小对象的高效内存管理,我还有什么其他选择吗?

您可以确保使用。在Vista和更高版本中,默认情况下它是打开的,但我认为早期的操作系统并非如此。这可能会大大提高小对象的分配速度。

或许可以尝试使用谷歌的?它是经过优化的用于在线程程序中快速分配/取消分配,并且对于小对象具有较低的开销。

某些实例也可能跨线程边界传递

只有“一些”?因此,如果这样做可以使无法传递给其他线程的线程变得更便宜,那么您也许可以为此支付额外的费用。我可以想出多种方法,让每个线程都有一个分配器,避免在分配或释放分配器所属的线程时需要锁定。我不知道在您的程序中可能有哪些方法:

  • 跨线程边界复制内容,而不是传递它们

  • 安排如果它们由于任何原因被传递到另一个线程,那么它们将被传递回原始线程以释放。这不一定经常发生,您可以在接收线程中排队,稍后在消息中将它们全部传递回。这当然假设拥有分配器的线程将被释放留下来

  • 每个分配器有两个空闲列表,一个是已同步的(当对象从另一个线程释放时会添加到其中),另一个是未同步的。仅当未同步列表为空且您正在分配时(因此在拥有分配器的线程中),是否需要锁定已同步的空闲列表并将其所有当前内容移动到未同步列表。如果传递给其他线程的对象很少,这基本上消除了互斥体上的争用,并大大减少了所花费的时间

  • 如果上述所有操作都失败了,那么每个线程有一个分配器可能仍然允许您摆脱互斥锁,并对空闲列表使用无锁队列(多个写入程序释放,单个读取程序分配),这可以稍微提高性能。实现无锁队列是平台特定的


再往后退一步,你的应用程序是否经常出现这样一种状态,即你知道在某一点之后分配的所有单元格(可能在过去有一点)都不再使用?如果是这样,并且假设你的小对象的析构函数没有做任何非常紧急的事情,那么在“某一点”根本不必释放单元格创建一个新的分配器,并将旧的分配器标记为不再用于新的分配。当您“点击状态”时,释放整个分配器及其基础缓冲区。如果“特定点”和“状态”如果对象非常小,为什么不按值传递呢?还有,您的许多小对象是相同的,还是都不同?如果是第一个,请查看boost.flyweight。您的问题中没有证据表明您实际上可以做得更好。您认为自己做得更好的原因是什么?当你写互斥体时,你是指一般的还是特别的互斥体?如果特别的话,那么CriticalSection会更好,只要你不跨越进程边界。我使用的是boost::mutex,它是通过Windows上的互锁API实现的。我不认为与Critical在性能上有什么大的区别第节。两个实例不太可能是相同的。有一个动态分配的实例,因为多个对象引用它们是常见的,并且它们都需要看到更改。鉴于单线程池解决方案已经导致了速度的大幅提高,我希望有一个线程安全的解决方案,速度几乎一样快。即使是堆分配器optim为固定大小的对象进行优化可能比通用分配器id预期的更快,并且可以完全避免碎片问题,但是我不知道如何编写堆分配器:(我正在Vista上进行测试,所以在这种情况下它已经打开了。但是值得知道,因为我支持XP。这是一个有趣的问题(更重要的是,因为我不必解决它:)。我很想看看最终的解决方案。“在某一点之后(也许过去有一点),它们不再使用了?”不幸的是,没有,它们在程序的整个生命周期中都被使用。接下来是每个线程一个分配器。如果我在某种TLS中创建了一个池分配器,它有空闲列表,会怎么样?然后我只需要偶尔进行一次同步过程,以防止对象从一个线程迁移到另一个线程,从而导致一个线程释放多个线程它分配?是的,听起来很有道理。从一个线程到另一个线程的漂移越慢,同步的频率就越低,开销也就越低。您还可以看看这个: