[#39845] Re: [ruby-cvs:33238] Ruby:r26022 (trunk): * marshal.c (w_object): dump instance variables when using — Tanaka Akira <akr@...>
2009/12/5 <nobu@ruby-lang.org>:
3 messages
2009/12/06
[#39846] [Bug #2447] reduce GC pressure by symbol table without String instance — Yusuke Endoh <redmine@...>
Bug #2447: reduce GC pressure by symbol table without String instance
5 messages
2009/12/06
[#39847] stable find.rb — Tanaka Akira <akr@...>
ディレクトリを再帰的にたどった結果を比較することがあったのですが、
5 messages
2009/12/06
[#39851] Time.now + str と #to_r — Yukihiro Matsumoto <matz@...>
まつもと ゆきひろです
9 messages
2009/12/07
[#39852] Re: Time.now + str と #to_r
— "NARUSE, Yui" <naruse@...>
2009/12/07
成瀬です。
[#39855] [RubySpec #2460] RubySpecでFiberのSpecがおちる — 三村 益隆 <redmine@...>
RubySpec #2460: RubySpecでFiberのSpecがおちる
4 messages
2009/12/08
[#39863] [Feature #2471] want to choose a GC algorithm — _ wanabe <redmine@...>
Feature #2471: want to choose a GC algorithm
8 messages
2009/12/09
[#39874] faster Enumerator#each by rb_block_call with current block — Yusuke ENDOH <mame@...>
遠藤です。
7 messages
2009/12/13
[#39894] Re: faster Enumerator#each by rb_block_call with current block
— Yukihiro Matsumoto <matz@...>
2009/12/19
まつもと ゆきひろです
[#39897] Re: faster Enumerator#each by rb_block_call with current block
— Yusuke ENDOH <mame@...>
2009/12/20
遠藤です。
[#39912] [Bug #2522] Segmentation Fault is occurred on r26158 by running rubyspec — Kenta Murata <redmine@...>
Bug #2522: Segmentation Fault is occurred on r26158 by running rubyspec
4 messages
2009/12/23
[ruby-dev:39874] faster Enumerator#each by rb_block_call with current block
From:
Yusuke ENDOH <mame@...>
Date:
2009-12-13 03:58:51 UTC
List:
ruby-dev #39874
遠藤です。
現在の Enumerator#each は、1 回のブロック呼び出しで 2 回分の yield を実行
しています。
1. Enumerator#each が元のメソッドを rb_block_call で呼ぶ
(このときブロックとして enumerator_each_i を与える)
2. 元のメソッドが yield して現在のブロック (enumerator_each_i) を呼ぶ
3. enumerator_each_i が yield して実際のブロックを呼ぶ
そこで rb_block_call に現在のブロックを渡せるようにしてみました。
こうすると、yield は 1 回で済みます。
1. Enumerator#each が元のメソッドを rb_block_call で呼ぶ
(このときブロックとして現在のブロックをそのまま渡す)
2. 元のメソッドが yield して実際のブロックを呼ぶ
以下のベンチマークで試すと、パッチ前で 1.49 秒、パッチ後で 1.00 秒と
なりました。
GC.disable
a = [0] * 5000000
t = Time.now
a.to_enum.each {|x| }
p Time.now - t
ちなみに a.to_enum.each の代わりに a.each と直接呼んだ場合でも 1.00 秒
です。メソッドをベースとした Enumerator が to_enum しない場合と遜色ない
速度になったと思います。
この話は Enumerator に特化した話ではなく、ARGF.each_line や each_byte
なども同じように 2 段階 yield になっていたので、現在のブロックを直接
渡すようにしたところ、以下が 0.20 秒から 0.18 秒に高速化しました。
ruby -e '$<.each_line {|l| }' *.c
具体的なパッチの内容は、rb_block_call の bl_proc に NULL が渡されたら
現在のブロックを使うようにするというものです。
コミットしてもいいでしょうか。
diff --git a/enumerator.c b/enumerator.c
index 7c50f3d..34d16c0 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -330,12 +330,6 @@ enumerator_allocate(VALUE klass)
}
static VALUE
-enumerator_each_i(VALUE v, VALUE enum_obj, int argc, VALUE *argv)
-{
- return rb_yield_values2(argc, argv);
-}
-
-static VALUE
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, VALUE *argv)
{
struct enumerator *ptr;
@@ -473,7 +467,7 @@ static VALUE
enumerator_each(VALUE obj)
{
if (!rb_block_given_p()) return obj;
- return enumerator_block_call(obj, enumerator_each_i, obj);
+ return enumerator_block_call(obj, 0, obj);
}
static VALUE
diff --git a/io.c b/io.c
index 643455e..3b8bd25 100644
--- a/io.c
+++ b/io.c
@@ -9148,7 +9148,7 @@ argf_each_line(int argc, VALUE *argv, VALUE argf)
RETURN_ENUMERATOR(argf, argc, argv);
for (;;) {
if (!next_argv()) return argf;
- rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv,
rb_yield, 0);
+ rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
ARGF.next_p = 1;
}
}
@@ -9182,7 +9182,7 @@ argf_each_byte(VALUE argf)
RETURN_ENUMERATOR(argf, 0, 0);
for (;;) {
if (!next_argv()) return argf;
- rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, rb_yield, 0);
+ rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
ARGF.next_p = 1;
}
}
@@ -9212,7 +9212,7 @@ argf_each_char(VALUE argf)
RETURN_ENUMERATOR(argf, 0, 0);
for (;;) {
if (!next_argv()) return argf;
- rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, rb_yield, 0);
+ rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
ARGF.next_p = 1;
}
}
diff --git a/vm_eval.c b/vm_eval.c
index f0b2316..9276f0a 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -828,9 +828,15 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
if (state == 0) {
iter_retry:
{
- rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
- blockptr->iseq = (void *)node;
- blockptr->proc = 0;
+ rb_block_t *blockptr;
+ if (bl_proc) {
+ blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp);
+ blockptr->iseq = (void *)node;
+ blockptr->proc = 0;
+ }
+ else {
+ blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
+ }
th->passed_block = blockptr;
}
retval = (*it_proc) (data1);
--
Yusuke ENDOH <mame@tsg.ne.jp>