Cache Aware Ruby Patch
quick and dirty hackだ。
# diff -u gc.c~ gc.c --- gc.c~ 2006-08-25 17:12:46.000000000 +0900 +++ gc.c 2006-10-03 10:47:08.000000000 +0900 @@ -1594,10 +1594,15 @@ int n = 0; for (i = 0; i < heaps_used; i++) { - RVALUE *p, *pend; + RVALUE *p, *pend; p = heaps[i].slot; pend = p + heaps[i].limit; for (;p < pend; p++) { + if ( (p+1) < pend) { + __asm__ __volatile__ ( + " prefetch (%0)\n" + : : "r" ((p+1)->as.basic.flags) ); + } if (p->as.basic.flags) { switch (TYPE(p)) { case T_ICLASS:
test/runner.rbを2回実行した時のL1キャッシュミス。
オリジナル
CPU: Core Solo / Duo, speed 2666.77 MHz (estimated) Counted DCACHE_PEND_MISS events (Weighted cycles of L1 miss outstanding) with a unit mask of 0x00 (Weighted cycles) count 100000 samples % app name symbol name 245481 33.9674 ruby os_each_obj 35576 4.9227 ruby gc_mark 35297 4.8841 ruby rb_clear_cache_by_id 34610 4.7890 ruby gc_mark_children 24372 3.3724 ruby st_foreach
Cache Aware Ruby Patch
CPU: Core Solo / Duo, speed 2666.77 MHz (estimated) Counted DCACHE_PEND_MISS events (Weighted cycles of L1 miss outstanding) with a unit mask of 0x00 (Weighted cycles) count 100000 samples % app name symbol name 102616 17.4094 ruby os_each_obj 33412 5.6685 ruby gc_mark 32908 5.5830 ruby gc_mark_children 26125 4.4322 vmlinux copy_page_range 25514 4.3286 ruby rb_clear_cache_by_id
L1キャッシュミスが2回runner.rbを実行した時245481回から102616回(約41.8%)へ減少している。
まあ、だからどーだつー話ではないが、そーゆー感じである。
アルゴリズムを一切変更しないでprefetchするだけのpeephole最適化でもこのくらいはいくということが分かったからよしとしたい。Ruby歴3時間のわたしでもツールがあればここまではいける。