スタック領域とヒープ領域の速度
会話の中で「ヒープに比べてスタック領域の方が処理が速い」という話が出てきて,なぜそうなのかすぐにわからなかった.後で考えてみれば,ヒープ領域はアドレスから参照するしかないので,ワンステップ余計な処理が必要だな,と気がついた.けれど,そのロジックだとヒープ領域参照にかかる時間に比べて,参照してから行う処理の時間が圧倒的に大きい場合,関係なくなるなぁと思った.
そこで{スタック領域, ヒープ領域}に用意したint型変数への代入と自作クラスのインスタンスへの操作の時間を測定してみた.
実験コード
int型変数への代入
#include <iostream> #include <ctime> double count_stack (int n); double count_heap (int n); double count_stack (int n) { int a; std::clock_t start = std::clock(); for (int i = 0; i < n; i++) { a = n; // 普通に代入 } std::clock_t end = std::clock(); return (double) (end - start) / CLOCKS_PER_SEC; } double count_heap (int n) { int *a = new int; std::clock_t start = std::clock(); for (int i = 0; i < n; i++) { *a = n; // 参照して代入 } std::clock_t end = std::clock(); delete a; return (double) (end - start) / CLOCKS_PER_SEC; } int main () { int n = 100000000; int LOOP_NUM = 10; double stack_mean = 0; double heap_mean = 0; for (int i = 0; i < LOOP_NUM; i++) { stack_mean += count_stack(n); heap_mean += count_stack(n); } std::cout << "stack: " << stack_mean / LOOP_NUM << std::endl; std::cout << "heap: " << heap_mean / LOOP_NUM << std::endl; return 0; }
自作クラスへの操作
class Person { int id; std::string name; public: Person (const int i, const char *n); // ~Person (); void set_name (std::string str); }; Person::Person (const int i, const char *n) { id = i; name = n; } void Person::set_name (std::string str) { name = str; // こいつのコストがヒープ領域1回参照に比べてかなり大きい } int main () { int n = 1000000; int LOOP_NUM = 10; double stack_mean = 0.0; double heap_mean = 0.0; for (int i = 0; i < LOOP_NUM; i++) { stack_mean += count_stack(n); heap_mean += count_heap(n); } std::cout << "stack: " << stack_mean / LOOP_NUM << std::endl; std::cout << "heap: " << heap_mean / LOOP_NUM << std::endl; return 0; }
結果
うーん,差が出ない...
本当は「intの方で差が出て,自作クラスの方で差がなくなる」という台本だったのですが,結果に差が出ませんでした.
このコードだとキャッシュにアドレスが残ってしまっているから?スタック領域の方が速い,どうすれば結果に表れるのでしょうか.
# int: 1億回x10試行平均 [sec] # -Oなし stack: 0.176563 heap: 0.179688 # -O1 stack: 0.0539063 heap: 0.05 # -O2 stack: 0.0523438 heap: 0.0484375 # -O3 stack: 0.0460938 heap: 0.05625 # 自作クラス 100万回x10試行平均 [sec] # なし stack: 0.195312 heap: 0.19375 # -O1 stack: 0.178906 heap: 0.179688 # -O2 stack: 0.151562 heap: 0.151562 # -O3 stack: 0.146875 heap: 0.148438