gpt4 book ai didi

c++ - 关于alloca的使用和滥用

转载 作者:IT老高 更新时间:2023-10-28 21:51:12 27 4
gpt4 key购买 nike

我正在开发一个软实时事件处理系统。我想尽量减少我的代码中具有不确定时间的调用。我需要构建一个由字符串、数字、时间戳和 GUID 组成的消息。可能是 boost::variantstd::vector

我一直想在过去类似性质的代码中使用 alloca。然而,当人们查看系统编程文献时,总是对这个函数调用非常谨慎。就我个人而言,在过去的 15 年中,我无法想到没有虚拟内存的服务器类机器,而且我知道 Windows 堆栈一次增长一个虚拟内存页面,所以我假设Unices也一样。这里(不再)没有砖墙,堆栈和堆一样可能会用完空间,所以什么给了?为什么人们不喜欢 aloca 呢?我可以想到许多负责任地使用 alloca 的用例(字符串处理任何人?)。

无论如何,我决定测试性能差异(见下文),alloca 和 malloc 之间存在 5 倍的速度差异(测试记录了我将如何使用 alloca)。那么,事情发生了变化吗?只要我们可以绝对确定对象的生命周期,我们是否应该小心翼翼地使用 alloca(包装在 std::allocator 中)?

我厌倦了生活在恐惧中!

编辑:

好的,所以有限制,对于 Windows,这是一个链接时间限制。对于 Unix,它似乎是可调的。似乎页面对齐的内存分配器是有序的:D 任何人都知道通用的可移植实现: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

最佳答案

首先,即使有很多虚拟内存并不意味着您的进程将被允许填充它。在 *nix 上有堆栈大小限制,而堆则更宽松。

如果您只打算分配几百/几千个字节,请务必继续。除此之外的任何事情都将取决于任何给定系统上的限制 (ulimit),而这只是灾难的根源。

Why is the use of alloca() not considered good practice?

在我工作的开发箱 (Gentoo) 上,我的默认堆栈大小限制为 8192 kb。这不是很大,如果 alloca 溢出堆栈,则行为未定义。

关于c++ - 关于alloca的使用和滥用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5807612/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com