为什么在预关注内存中创建对象慢,而不是单独为每个对象分配内存的对象
Why creating objects in preallocated memory slow than creating objects with allocating memory for each object individually?
我有一个内存池,它表示为免费内存块列表,我需要在"放置新"中使用这些块,因为将对象存储在预关注的内存中可能比为每个分配内存的内存更快单独对象。
我有两个代码段,使用"新"关键字创建对象。
第一个代码剪切:使用内存池提供的内存中的"位置新"内存中创建的对象。第二个代码剪切:在不使用预关注内存的情况下创建对象,只需使用"新"。
为什么基于放置新慢的剪切而不是剪切而没有放置新的?
首先剪辑:
#include <chrono>
#include <iostream>
struct list
{
list *next;
};
class Test
{
public:
int a;
int b;
};
void* getPtr()
{
static int init = 0;
static list *head;
static list *free;
if (!init) {
std::cout << "Initialized." << std::endl;
init = 1;
list *head = reinterpret_cast<list*>(new char(sizeof(Test)));
free = head;
for (int i = 0; i < 10000000; i++) {
head->next = reinterpret_cast<list*>(new char(sizeof(Test)));
head = head->next;
}
}
list *ret = free;
free = ret->next;
return ret;
}
int main()
{
getPtr();
auto begin = std::chrono::high_resolution_clock::now();
for(int i = 0; i < 10000000; i++) {
new(getPtr())Test();
}
auto end = std::chrono::high_resolution_clock::now();
std::cout<<std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count()<<" ns"<< std::endl;
}
第二个剪切
#include <chrono>
#include <iostream>
class Test
{
public:
int a;
int b;
};
int main()
{
auto begin = std::chrono::high_resolution_clock::now();
for(int i = 0; i < 10000000; i++) {
new Test();
}
auto end = std::chrono::high_resolution_clock::now();
std::cout<<std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count()<<" ns"<< std::endl;
}
我以前从未写过记忆池,但我想您想(至少)(至少)3件事:
-
内存对齐
-
当池脱离范围时,会破坏分配的对象。
-
现场
new
的返回值
我在这里尝试过并写了同等测试
struct destroy_not_free
{
template<class T>
void operator()(T* p) const { p->~T(); }
};
template<class Jobbie>
struct memory_pool {
using buffer_type = std::aligned_storage<sizeof(Jobbie), alignof(Jobbie)>;
memory_pool(std::size_t limit)
: memptr_(std::make_unique<buffer_type[]>(limit)), limit_(limit), used_(0)
{
allocated_.reserve(limit);
}
memory_pool(const memory_pool&) = delete;
memory_pool(memory_pool&&) = default;
memory_pool& operator=(const memory_pool&) = delete;
memory_pool& operator=(memory_pool&&) = delete;
template<class...Args>
Jobbie *create(Args &&...args) {
if (used_ < limit_) {
auto candidate = new(std::addressof(memptr_[used_])) Jobbie(std::forward<Args>(args)...);
allocated_.emplace_back(candidate);
++ used_;
return candidate;
}
else {
throw std::bad_alloc();
}
}
// NOTE: order important. We want the vector of unique_ptr to
// be destroyed before the memory buffer otherwise calling the
// destructors will result in software armageddon
std::unique_ptr<buffer_type[]> memptr_;
std::vector<std::unique_ptr<Jobbie, destroy_not_free>> allocated_;
std::size_t limit_;
std::size_t used_;
};
class Test {
public:
int a;
int b;
};
int main() {
{
auto pool = memory_pool<Test>(10000000);
auto begin = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000000; i++) {
pool.create();
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "with memory pool: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms" << std::endl;
}
{
std::vector<std::unique_ptr<Test>> v;
v.reserve(10000000);
auto begin = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 10000000; i++) {
v.emplace_back(new Test());
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "with new : " << std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() << " ms" << std::endl;
}
}
在3岁旧iMac上与苹果clang 8,-o2:
编译的结果with memory pool: 59 ms
with new : 842 ms
相关文章:
- 迭代时从向量和内存中删除对象
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 对具有动态分配的内存和析构函数的类对象的引用
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 内存清理程序报告全局对象构造中未初始化值的使用
- 如何删除列出的"QGraphicsPathItem"对象以控制进程内存使用情况?
- 准确了解对象在内存中的映射方式
- 完全释放静态对象内存
- C++ 对象内存管理
- 循环中的自动变量和自动对象内存分配
- 每个对象内存分配有多少开销
- 是隐式创建的默认构造函数,负责分配对象内存
- 使用 make_unique 语句重新分配unique_ptr对象 - 内存泄漏
- C++对象内存布局
- C++对象内存消耗
- 谷歌模拟全局模拟对象内存泄漏
- 静态工厂方法和静态对象内存泄漏
- 关于对象内存布局的假设
- 如果我在管理C++对象内存的目标 C 中混合C++代码,ARC 会处理它