K.Sasada's Home Page

Diary - 2012 October

研究日記

神無月

_18(Thu)

inline method cache をよりよくする方法を思いついた気がしたんだけど,気のせいだったという話.

今は,vmstate(キャッシュしたときの状態)+CLASS_OF(recv) が等しければキャッシュヒットとしていたんだけど,必ず CLASS_OF(recv) のコストがかかってしまう.どうにかなんないものか,とずっと考えていた(数年来).

で,今回の変更で recv をインラインキャッシュと同じ構造体に突っ込んでいるんで,それなら recv と比較してマッチすれば,それはヒットにすればいいじゃん,という話.

つまり,vmstat が同じ,かつ(recv が同じ,または,CLASS_OF(recv) が同じ)とすればいいじゃん,という.で,それをコードにしたのが以下.

static void
vm_search_method(rb_call_info_t *ci, VALUE recv)
{
    VALUE klass;
    rb_method_entry_t *me;

#if OPT_INLINE_METHOD_CACHE
    if (LIKELY(GET_VM_STATE_VERSION() == ci->vmstat)) {
	if (recv == ci->recv) {
	    /* cache hit! */
	    goto finish;
	}
	else if ((klass = CLASS_OF(recv)) == ci->klass) {
	    /* cache hit! */
	    ci->recv = recv;
	    goto finish;
	}
	else {
	    goto klass_was_stored;
	}
    }
    else {
	klass = CLASS_OF(recv);
      klass_was_stored:
	me = rb_method_entry(klass, ci->mid, &ci->defined_class);
	ci->me = me;
	ci->recv = recv;
	ci->klass = klass;
	ci->vmstat = GET_VM_STATE_VERSION();
	ci->call = vm_call_general;
    }
  finish:;
#else
    klass = CLASS_OF(recv);
    ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class);
    ci->call = vm_call_general;
    ci->klass = klass;
    ci->recv = recv;
#endif
}

goto とか使ってちょっと判りづらくなってるけど.

キャッシュミスのときのオーバヘッドは recv == ci->recv の判定のみなので,そんなにたいしたことないだろう,と思う.

で,これだとまずいことがわかったので reject.ci->recv は mark 対象じゃないので,GC される可能性があり,すなわち「たまたま recv が同じ場合がある」という話.ガーン.


あと,時間測ってみたら,殆どきかんかった....そもそも,ここはオーバヘッドじゃなかったのか?

http://www.atdot.net/fp_store/f.qt03cm/file.graph.png trunk が入れた結果で,効果なかったという.

_shiro(Thu Oct 18 19:39:02 +0900 2012)

 CLASS_OFってそんなに重いんですか?

_4(Thu)

いろいろうまくいかないことばかりでムシャクシャして,簡単にできるところだけコミットしてしまった.

Sasada Koichi / ko1 at atdot dot net
$Date: 2003/04/28 10:27:51 $