[#42194] Enhancing Numeric#step — "Akinori MUSHA" <knu@...>

 Numeric#step の仕様の拡張を提案します。

26 messages 2010/09/08
[#42196] Re: Enhancing Numeric#step — Yukihiro Matsumoto <matz@...> 2010/09/08

まつもと ゆきひろです

[#42200] Re: Enhancing Numeric#step — "Akinori MUSHA" <knu@...> 2010/09/08

At Wed, 8 Sep 2010 22:46:57 +0900,

[#42204] Re: Enhancing Numeric#step — Yukihiro Matsumoto <matz@...> 2010/09/09

まつもと ゆきひろです

[#42232] 1.9.2 readline can't handle cursorkeys, mbcs chars etc (msvcrt) — arton <artonx@...>

artonです。

11 messages 2010/09/10

[#42269] [Ruby 1.9-Bug#3836] Kernel.system, spawnがスペースを含むパスで動作しない — Hiroki Najima <redmine@...>

チケット #3836 が更新されました。 (by Hiroki Najima)

12 messages 2010/09/16
[#42270] WindowsでのKernel.systemの挙動、一貫性について — NAJIMA Hiroki <h.najima@...> 2010/09/16

名島(Nazy)と申します。

[#42310] ビジースレッドがあるとコンテキストスイッチが起きづらくなる — kuwamoto shintaro <beuniv@...>

こんにちは。

9 messages 2010/09/29
[#42315] [bug:trunk] ビジースレッドがあるとコンテキストスイッチが起きづらくなる — "U.Nakamura" <usa@...> 2010/09/30

こんにちは、なかむら(う)です。

[ruby-dev:42304] Re: [Ruby 1.9-Bug#3696][Closed] Fwd: [ruby-list:47272] case when 整数と実数の比較 (ruby 1.9)

From: SASADA Koichi <ko1@...>
Date: 2010-09-27 14:27:11 UTC
List: ruby-dev #42304
 ささだです。

 この件があって、opt_case_dispatch を見ていたんですが、ヒットしないとき
の挙動について、少し考えてみました。

 ヒットしないとき(型がこの最適化できる型じゃなかった、もしくは値が違っ
た)ときは、st_foreach で === を行い、case/when を実現しています。です
が、いくつかの理由から(たぶん)、=== を順に行うバイトコードも(無駄に)
生成されています。つまり、opt_case_dispatch から、単に抜けるだけでも、き
ちんと === をするわけです。

 さて、どっちが速いのか、と調べたところ、st_foreach よりも、バイトコー
ド実行に任せたほうが若干速いことがわかりました。st_foreach でたどるリス
トが長ければ長いほど、その傾向が顕著であることがわかりました。

 理由は、foreach でたどるよりも VM でたどる方が速いとか、そういうのだと
思います。

 というわけで、その報告と、修正をお送りします。


 何度も同じハッシュに対して Hash#each するようなコードは eval で展開し
ちゃった方が速いかもね、という知見でもありますが、さてそういうケースはど
れだけあるんだろうか?

mswin32
http://www.atdot.net/fp_store/f.0tse9l/file.graph.png

linux32 (on VirtualBox)
http://www.atdot.net/fp_store/f.7tse9l/file.graph.png

グラフは、
横軸が「失敗する when の数(st_foreach でたどる回数)」
縦軸が「実行時間(秒)」
です。

ちなみに、もちろんヒットするときは when の数は関係なく速いです。


テストコード:
require 'benchmark'

n = 10_000_000
Benchmark.bm{|x|
  [true, false, Object.new].each{|obj|
    20.times{|i|
      ary = (0..i).to_a
      obj = i if obj == true
      x.report("#{obj}\t#{i+1}"){
        eval %Q{
          n.times{
            case obj
            when #{ary.join(", ")}
              # ignore
            else
              # ignore
            end
          }
        }
      }
    }
  }
}

パッチ:

Index: insns.def
===================================================================
--- insns.def	(revision 29350)
+++ insns.def	(working copy)
@@ -1281,20 +1281,8 @@
 	    }
 	    break;
 	}
-      default: { /* fall through (else) */
-	struct opt_case_dispatch_i_arg arg;
-
-	arg.obj = key;
-	arg.label = -1;
-	st_foreach(RHASH_TBL(hash), opt_case_dispatch_i, (st_data_t)&arg);
-
-	if (arg.label != -1) {
-	    JUMP(arg.label);
-	}
-	else {
-	    JUMP(else_offset);
-	}
-      }
+      default:
+	break;
     }
 }

Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 29350)
+++ vm_insnhelper.c	(working copy)
@@ -1699,22 +1699,3 @@
     return Qundef;
 }

-struct opt_case_dispatch_i_arg {
-    VALUE obj;
-    int label;
-};
-
-static int
-opt_case_dispatch_i(st_data_t key, st_data_t data, st_data_t p)
-{
-    struct opt_case_dispatch_i_arg *arg = (void *)p;
-
-    if (RTEST(rb_funcall((VALUE)key, idEqq, 1, arg->obj))) {
-	arg->label = FIX2INT((VALUE)data);
-	return ST_STOP;
-    }
-    else {
-	return ST_CONTINUE;
-    }
-}
-

-- 
// SASADA Koichi at atdot dot net

In This Thread

Prev Next