xyzzyの内部構造 更新日付:2009/11/14 xyzzyのソースを調べたメモ(書きかけ) メモリ管理(alloc.h、alloc.cc) テキストバッファは、チャンク(塊)の双方向リンクリストで構成 一つのチャンクは4096文字=4096×2byte=8192byte チャンクのメモリ割り当て fixed_heap ↓ alloc_page alloc_pageは、ランタイムライブラリのmallocやnewは使用していない Win32 APIのHeapAllocも使用していない VirtualAllocを使用して、アドレスの予約を64KB単位で行い、 そこからページ単位(4096byte)でコミットを行いメモリの割り当てを行っている。 ■malloc、newやHeapAllocよりも高速なのか? VirtualAllocを使用して独自にメモリアロケータを実装するのは mallocなどC/C++の標準関数やWindowsAPIのHeapAllocを使用するよりも高速なのか? 実験を行ってみた。 ★実験1 測定条件: ・20000回連続でallocした後、20000回freeするという動作を10回繰り返す ・1回の割り当てサイズ 4096(ページサイズ) ・最適化オプション/Oxでコンパイル ・測定マシン:Core 2 Quad 9550 単位(ms) page_alloc : 586 (alloc : 311, free : 275) malloc : 358 (alloc : 258, free : 100) new : 405 (alloc : 301, free : 104) HeapAlloc : 395 (alloc : 297, free : 98) ※page_allocがxyzzyが実装しているメモリアロケータ ※単位はms 結果 page_allocがalloc、freeともに最も遅いという結果になった。 ログを追加してボトルネックの箇所を特定したところ、 ページのコミット/デコミットに90%近くの時間を消費していた。 そこで、xyzzyで実装されているようにページ単位でのコミット/デコミットを行わず、 アドレス予約単位で予約(同時にコミット)/解放を行い、そこからページ単位のメモリを 内部で管理して割り当てるように変更して測定してみた。 ★実験2 page_alloc : 305 (alloc : 245, free : 60) malloc : 393 (alloc : 307, free : 86) new : 379 (alloc : 301, free : 78) HeapAlloc : 371 (alloc : 285, free : 86) 結果 alloc、freeともに最も早くなった。 xyzzyのテキストバッファにはalloc_pageが使用されているが、 int型などのサイズの小さいメモリのヒープ管理は、fixed_heapを介してalloc_pageが使用されている。 fixed_heapでintの配列をヒープで割り当てる場合の速度についても測定してみた。 ★実験3 測定条件: ・20000回連続でallocした後、20000回freeするという動作を10回繰り返す ・1回の割り当てサイズ int(4byte) ・最適化オプション/Oxでコンパイル ・測定マシン:Core 2 Quad 9550 fixed_heap : 220 (alloc : 1, free : 219) malloc : 56 (alloc : 28, free : 28) new : 56 (alloc : 28, free : 28) HeapAlloc : 27 (alloc : 14, free : 13) 結果 allocはきわめて高速だが、freeが非常に遅いという結果になった。 page_allocをアドレス予約単位で予約(同時にコミット)/解放を行うように 変更したバージョンで測定してみた。 ★実験4 fixed_heap : 120 (alloc : 1, free : 119) malloc : 56 (alloc : 27, free : 29) new : 54 (alloc : 28, free : 26) HeapAlloc : 27 (alloc : 14, free : 13) 結果 freeが半分になったが、それでもmallocなどに比べてかなり遅い。 以上の4つの実験から言えることは、xyzzyのメモリ管理は残念ながら非効率で、 ランタイムライブラリのmallocやnewを使用した方がましということだ。 ただし、テキストバッファの管理にはpage_allocのコミット/デコミットの単位を アドレス予約の単位に改良することでmalloc、newよりも効率的になる。 また、実験の結果からmalloc、new、HeapAllocのメモリ管理は非常に優秀だということがわかった。 malloc、new、HeapAllocの中では、ほぼ同等の結果だが、メモリサイズが小さい場合HeapAllocが特に高速である。