不同内存分配方式的时间差异
不同内存分配方式的时间差异
自从开始熟悉的cpp的指针写法后,我在使用疯狂使用指针的路上一去不复返(苦笑)。然而,自此之后,我发现自己的程序总是比别人慢半拍(其实不止半拍。。)。于是想要比较一下不同写法的差异。没想得,只是写了一下内存分配的部分,就发现了问题的根源所在。。。
分析
在这里,我们通过对新建\(10^7\)个Node结构体来比较不同的分配方法所花费的时间。并且,我们在分配完成后进行一次初始化操作。Node结构体如下: 1
2
3
4
5
6struct Node
{
int x;
Node (int x = 0):x(x) {}
};
我们的所有操作都是在以下的循环体内进行: 1
2
3
4for (int i = 0; i<MAXN; i++)
{
true//code here
}
首先,我们考虑的是最常用的情况:直接定义,赋值。代码为:Node x = Node(i);。经多次实验,所花费的时间大概为31ms。
然后,便是指针写法。代码为:Node *x = new Node(i);。所花费时间大致为500ms到600ms。
此外,我们尝试了一下提前获取内存空间,然后在需要指针时将已经获取到的内存空间分配给当前指针的写法。这里的写法是一个较为普适性的写法,使用了一个MemoryPool的结构体,若是只需分配一种结构体的空间则可以不用这么麻烦。MemoryPool的写法参照于Menci,写法如下: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22template <size_t SIZE>
struct MemoryPool
{
char buf[SIZE], *cur;
MemoryPool():cur(buf) {}
void *malloc(int size)
{
if (size + cur > buf + SIZE)
{
cout << "out of memory" << endl;
return malloc(size);
}
char *p = cur;
cur += size;
return (void *)p;
}
};
MemoryPool<sizeof(Node) * MAXN> pool;1
2Node *x = (Node*)pool.malloc(sizeof(Node));
*x = Node(i);
该方法的循环执行时间大概为90ms,加上大致30ms的初始内存分配时间,大致为120ms。
另外,此时的循环内代码通过引用new头文件(#include <new>),可以简写为Node *x = new ((Node*)pool.malloc(sizeof(Node))) Node(i);,对运行时间没有什么影响。
由此,我们可以得出结论。各方法的时间比约为\(1:20:4\)。也就是说,若是为了运行效率考虑,还是普通的直接定义使用的方法优先。但若是想用指针又想较为快速的话,也可以使用第三种方法,不过这样令变量的生命周期更加难于管理,所以在实际工程中不建议使用,在竞赛中可以作为优化指针速度的一种手段。
完整代码
1 |
|