自定义分配器,新建/删除与malloc()/ free()

时间:2019-10-13 14:16:28

标签: c++ dynamic-memory-allocation

因此,这个问题主要是由于类似以下的帖子引起的:
Why are new()/delete() slower than malloc()/free()?

在以下情况下考虑自己:

  • 您主要使用普通的旧数据类型,并且您需要做很多事情 分配/取消分配
  • 您使用连续的内存块
  • 出于某种原因,性能确实非常重要...


这个想法是要提出一个新的分配器类,它可以在两个方法malloc()std::allocator之间“选择”。

假设如果您的类型不是 POD类型,您将使用namespace meta { template<bool, typename T> struct Allocator_Impl; template<typename T> struct Allocator_Impl<true, T> { using type = Mallocator<T>; }; template<typename T> struct Allocator_Impl<false, T> { using type = std::allocator<T>; }; template<typename T> struct is_trivially_allocateable { using type = typename std::conjunction<std::is_trivial<T>, std::is_standard_layout<T>>::type; constexpr static inline bool value = type::value; }; } template<typename T> struct Allocator : public meta::Allocator_Impl<meta::is_trivially_allocateable<T>::value, T> {}; ,并使用这样的分配器,如下所述:https://en.cppreference.com/w/cpp/named_req/Allocator(Mallocator)< br />如果您的类型是POD类型

现在,要选择分配器类,您将使用类似以下内容的内容:

vector



在此之后,要实施我们的“智能”?例如,我们可以简单地从旧的sna类继承容器。假设这里的向量在另一个命名空间中,例如namespace sna { template<typename T> using allocTy = typename Allocator<T>::type; template<typename T, class Alloc = allocTy<T>> class vector : public std::vector<T, Alloc> { public: typedef typename std::vector<T, Alloc>::size_type size_type; typedef T value_type; typedef Alloc allocator; typedef std::vector<value_type, allocator> parent; vector() : parent() {} vector(const size_type n) : parent(n) ... implement other constructors if needed ... }; }

std::chrono::system_clock::time_point start, stop;

const size_t size = 100000000;
std::cout << "Allocating " << size << " doubles:" << std::endl;

start = std::chrono::high_resolution_clock::now();
std::vector<double> new_data(size);
stop = std::chrono::high_resolution_clock::now();
std::cout << "Duration with normal vector: ";
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count() << " ns." << std::endl;

start = std::chrono::high_resolution_clock::now();
sna::vector<double> malloc_data(size);
stop = std::chrono::high_resolution_clock::now();
std::cout << "Duration with custom vector: ";
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count() << " ns." << std::endl;



之后-为了确保-我也对分配时间进行了基准测试,并提出了:

  

分配1亿双:
  法线向量的持续时间:281528400 ns。
  带有自定义矢量的持续时间:1990600 ns。



对于基准测试,我使用了这段代码:

vector



对于此基准测试,我使用了-O2优化标志。
因此,对我来说,使用Mallocator类的std::allocator比使用std::vector的{​​{1}}快一百倍,我认为这是相当可观的性能提升。

但除此之外:
这样的“把戏”是否被认为是不好的做法?或者,如果情况如上所述,您可以安全地使用这样的东西吗?是否会有另一个更好的解决方案,否则这将不值得付出努力,而我应该坚持使用{{1}}类型?

0 个答案:

没有答案