私はソフトリアルタイムイベント処理システムに取り組んでいます。非決定的なタイミングを持つコード内の呼び出しを最小限に抑えたいと考えています。文字列、数字、タイムスタンプ、および GUID で構成されるメッセージを作成する必要があります。おそらくstd::vector
のboost::variant
の。
私はいつもalloca
似たような性質の過去のコードで使いたいと思っていました。ただし、システム プログラミングの文献を調べると、この関数呼び出しに対して常に大きな注意が払われています。個人的には、過去 15 年間、仮想メモリを持たないサーバー クラスのマシンは考えられません。また、Windows スタックが一度に 1 ページずつ仮想メモリを拡張するという事実を知っているので、ユニスも同様です。ここには(もう)レンガの壁はありません。スタックはヒープと同じくらいスペースが不足する可能性があります。人々がアロカよりもガガにならないのはなぜですか? alloca を責任を持って使用する多くのユースケースを思いつくことができます (文字列処理は誰ですか?)。
とにかく、パフォーマンスの違いをテストすることにしました (以下を参照)。alloca と malloc の間には 5 倍の速度の違いがあります (テストは alloca の使用方法をキャプチャします)。それで、物事は変わりましたか?風に注意を払い、オブジェクトの寿命を完全に確信できる場合はいつでもalloca
( a でラップされた) を使用する必要がありますか?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