我正在开发一个软实时事件处理系统。我希望尽可能减少代码中具有非确定性时间的调用。我需要构建一个包含字符串、数字、时间戳和GUID的消息,可能使用
std::vector
和boost::variant
。
在过去的类似项目中,我一直想使用alloca
函数。然而,在研究系统编程文献时,总是会对这个函数调用提出巨大的警告。就我个人而言,过去15年中没有一台服务器级别的机器没有虚拟内存,我还知道Windows堆栈一页一页地增长虚拟内存,因此我认为UNIX也是如此。这里没有任何难以逾越的障碍了(不再存在),堆栈空间和堆一样容易用完,那么问题来了?为什么人们不疯狂地追捧alloca
呢?我可以想到许多使用alloca
的负责任的用例(比如字符串处理)。
无论如何,我决定测试性能差异(见下文),并且alloca
和malloc之间有5倍的速度差异(测试涵盖了我如何使用alloca
)。所以,情况是否已经改变?我们是否应该放弃谨慎,只要我们能绝对确定对象的生命周期,就使用alloca
(包装在std::allocator
中)呢?
我已经厌倦了生活中的恐惧!
编辑:
好吧,这里有限制:对于Windows系统,它是一个链接时的限制。对于Unix系统,似乎是可以调整的。需要一个页面对齐内存分配器:D 有人知道通用的可移植实现方法吗?
代码:
#include <stdlib.h>
#include <time.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using namespace boost::posix_time;
int random_string_size()
{
return ( (rand() % 1023) +1 );
}
int random_vector_size()
{
return ( (rand() % 31) +1);
}
void alloca_test()
{
int vec_sz = random_vector_size();
void ** vec = (void **) alloca(vec_sz * sizeof(void *));
for(int i = 0 ; i < vec_sz ; i++)
{
vec[i] = alloca(random_string_size());
}
}
void malloc_test()
{
int vec_sz = random_vector_size();
void ** vec = (void **) malloc(vec_sz * sizeof(void *));
for(int i = 0 ; i < vec_sz ; i++)
{
vec[i] = malloc(random_string_size());
}
for(int i = 0 ; i < vec_sz ; i++)
{
free(vec[i]);
}
free(vec);
}
int main()
{
srand( time(NULL) );
ptime now;
ptime after;
int test_repeat = 100;
int times = 100000;
time_duration alloc_total;
for(int ii=0; ii < test_repeat; ++ii)
{
now = microsec_clock::local_time();
for(int i =0 ; i < times ; ++i)
{
alloca_test();
}
after = microsec_clock::local_time();
alloc_total += after -now;
}
std::cout << "alloca_time: " << alloc_total/test_repeat << std::endl;
time_duration malloc_total;
for(int ii=0; ii < test_repeat; ++ii)
{
now = microsec_clock::local_time();
for(int i =0 ; i < times ; ++i)
{
malloc_test();
}
after = microsec_clock::local_time();
malloc_total += after-now;
}
std::cout << "malloc_time: " << malloc_total/test_repeat << std::endl;
}
输出:
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056302
malloc_time: 00:00:00.260059
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056229
malloc_time: 00:00:00.256374
hassan@hassan-desktop:~/test$ ./a.out
alloca_time: 00:00:00.056119
malloc_time: 00:00:00.265731
--编辑:在本机、clang和google perftools上的结果--
G++ without any optimization flags
alloca_time: 00:00:00.025785
malloc_time: 00:00:00.106345
G++ -O3
alloca_time: 00:00:00.021838
cmalloc_time: 00:00:00.111039
Clang no flags
alloca_time: 00:00:00.025503
malloc_time: 00:00:00.104551
Clang -O3 (alloca become magically faster)
alloca_time: 00:00:00.013028
malloc_time: 00:00:00.101729
g++ -O3 perftools
alloca_time: 00:00:00.021137
malloc_time: 00:00:00.043913
clang++ -O3 perftools (The sweet spot)
alloca_time: 00:00:00.013969
malloc_time: 00:00:00.044468