在之前轨迹的中看到了一段代码:
TrajectoryAnalyzer()类中一个 构造函数,函数接收的是轨迹信息。在个构造函数中使用std::vector管理轨迹点,其实是逐个轨迹点push_back。
同时又看了一地段Eigen的代码,同样使用了std:vector,但是使用了自己内存分配器:
template
class vector: protect _Vector_base
同样的vector使用默认的或者用户实现的分配器件在性能上有什么区别?vector的表现又是如何?
先看一段测试程序:
#include
#include
#include "time.hpp"
struct Point
{
Point() = default;
Point(double x_,double y_,double z_,double h_,double v_)
{
//std::cout<<"Create Point with params : "<
struct MyAllocator {
using value_type = T;
MyAllocator() noexcept {}
template
MyAllocator(const MyAllocator&) noexcept {}
template
void construct(T* p, Args&&... args)
{
//std::cout << "Constructing one at "<< p <(args)...);
};
T* allocate(std::size_t n) {
std::cout<<"Try to allocate "< std::size_t(-1) / sizeof(T)) {
throw std::bad_alloc();
}
if (auto p = static_cast(std::malloc(n * sizeof(T)))) {
return p;
}
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t) noexcept {
std::cout<<"Release all the region"<>
using MyVector = std::vector;
int main() {
MyVector myVector;
myVector.reserve(1024);
std::cout<<"Try to push 1024 elements "< v;
v.reserve(1024);
std::cout<
解释一下提交allocator是一个类,类的表达是有格式的。按照格式分别实现:
1,分配内存 - 使用operator new(只分配不构造)
2,销毁内存 - free(看来operator new就是malloc)
3,构造对象 - placement new (在一个地址上构造一个对象)
4,插入对象 - (1)当用户使用自己的分配器,并且有construct函数时候,不论push_back或emplace_back一律调用construct在容器中构造对象。
- (2)当使用默认的分配器时候,push_back和emplace_back的表现不一致,push_back耗时明显大于emplace_back。
5,时间函数 - 前后对比,判断耗时。
下面把测试结果分别显示一下:
测试环境:jetson orin ubuntu 20.04
1,默认的分配方式push_back插入数据和用户自定义的allocator插入数据比较:
Try to allocate 40960 bytes
Try to push 1024 elements
2023-09-15 16:05:39.879776909
2023-09-15 16:05:39.879906062
1
2
3
4
5
2023-09-15 16:05:39.879963790
2023-09-15 16:05:39.880002639
12953 ns
38849 ns
用户分配器使用placement new在已分配好的内存上构造13微秒
使用默认的分配器耗时明显比多。
2,默认的分配方式emplace_back插入数据和用户自定义的allocator插入数据比较:
2023-09-15 16:46:17.482801219
2023-09-15 16:46:17.482927142
1
2
3
4
5
2023-09-15 16:46:17.482970918
2023-09-15 16:46:17.483009799
125923 ns
38881 ns
使用emplace_back速度优于用户实现的插入操作。
总结:
1,我们看到代码中针对vector先使用reserve操作,预分配了一块内存,因此在插入过程中没有动态的更具内存大小实时调整,vector的调整是有拷贝的,把旧的数据内容拷贝到新的内存空间中。因此,vector预留内存的做法耗时较小,可以和没有reserve的vector比较一下:reserve预先分配内存方式下耗时小。
2,如果真有效率考量的话,还是建议使用emplace_back的操作,原理就是placement_new操作。在一块已知的内存上构造一个元素。
3,再次体验了一下C++中内存操作,作为语言C++考虑确实比较全面:
(1),只分配不构造
(2),分配和构造
(3),在一块空闲内存上分配对象
这也是new的三种不同用法。
谢谢