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が特に高速である。