抛弃std::allocator以支持自定义解决方案的一些真正好的理由是什么?您是否遇到过这样的情况:它对于正确性、性能、可伸缩性等来说是绝对必要的?有什么聪明的例子吗?
自定义分配器一直是标准库的一个特性,但我并不太需要它。我只是想知道是否有人能提供一些令人信服的例子来证明他们的存在。
抛弃std::allocator以支持自定义解决方案的一些真正好的理由是什么?您是否遇到过这样的情况:它对于正确性、性能、可伸缩性等来说是绝对必要的?有什么聪明的例子吗?
自定义分配器一直是标准库的一个特性,但我并不太需要它。我只是想知道是否有人能提供一些令人信服的例子来证明他们的存在。
当前回答
我没有使用自定义STL分配器编写c++代码,但我可以想象一个用c++编写的web服务器,它使用自定义分配器自动删除响应HTTP请求所需的临时数据。自定义分配器可以在生成响应后立即释放所有临时数据。
自定义分配器(我已经使用过)的另一个可能的用例是编写一个单元测试来证明函数的行为不依赖于它的某些输入。自定义分配器可以用任何模式填充内存区域。
其他回答
正如我在这里提到的,我已经看到英特尔TBB的自定义STL分配器仅通过更改单个STL分配器就显著提高了多线程应用程序的性能
std::vector<T>
to
std::vector<T,tbb::scalable_allocator<T> >
(这是一种快速方便的方式切换分配器使用TBB的漂亮的线程私有堆;见本文件第7页)
一种基本情况:当编写必须跨模块(EXE/DLL)边界工作的代码时,必须保持分配和删除只发生在一个模块中。
我在Windows上的插件架构中遇到了这种情况。例如,如果你跨DLL边界传递一个std::string,任何字符串的重新分配都发生在它起源的堆中,而不是在DLL中的堆中,这可能是不同的*。
*实际上比这更复杂,如果你动态链接到CRT,这可能会工作。但是,如果每个DLL都有一个到CRT的静态链接,那么您将陷入痛苦的世界,在那里幻影分配错误不断发生。
I personally use Loki::Allocator / SmallObject to optimize memory usage for small objects — it show good efficiency and satisfying performance if you have to work with moderate amounts of really small objects (1 to 256 bytes). It can be up to ~30 times more efficient than standard C++ new/delete allocation if we talk about allocating moderate amounts of small objects of many different sizes. Also, there's a VC-specific solution called "QuickHeap", it brings best possible performance (allocate and deallocate operations just read and write the address of the block being allocated/returned to heap, respectively in up to 99.(9)% cases — depends on settings and initialization), but at a cost of a notable overhead — it needs two pointers per extent and one extra for each new memory block. It's a fastest possible solution for working with huge (10 000++) amounts of objects being created and deleted if you don't need a big variety of object sizes (it creates an individual pool for each object size, from 1 to 1023 bytes in current implementation, so initialization costs may belittle the overall performance boost, but one can go ahead and allocate/deallocate some dummy objects before the application enters it's performance-critical phase(s)).
标准的c++ new/delete实现的问题是,它通常只是C malloc/free分配的包装器,它适用于较大的内存块,比如1024+字节。它在性能方面有显著的开销,有时还会占用额外的内存用于映射。因此,在大多数情况下,自定义分配器的实现方式是最大化性能和/或最小化分配小对象(≤1024字节)所需的额外内存量。
我没有使用自定义STL分配器编写c++代码,但我可以想象一个用c++编写的web服务器,它使用自定义分配器自动删除响应HTTP请求所需的临时数据。自定义分配器可以在生成响应后立即释放所有临时数据。
自定义分配器(我已经使用过)的另一个可能的用例是编写一个单元测试来证明函数的行为不依赖于它的某些输入。自定义分配器可以用任何模式填充内存区域。
使用自定义分配器来使用内存池而不是堆可能会很有用。这只是众多例子中的一个。
对于大多数情况,这肯定是一个不成熟的优化。但它在某些情况下(嵌入式设备、游戏等)非常有用。