search
LoginSignup
1

More than 1 year has passed since last update.

posted at

updated at

irb でサクっとパフォーマンスを調べる

irb の進化が止まらない。最も先進的な REPL は Ruby の irb かもしれない1。複数行編集,シンタックスハイライト,オートインデント,メソッド名補完は衝撃的だった。

さて,2020 年 12 月 20 日リリースの irb 1.2.8 で measure という機能が追加された。
これは式の評価にかかる時間を計測してくれるもの。

Ruby で 100 万番目の素数を表示するのは

require "prime"
p Prime.lazy.drop(999999).first

と書けばいい。答えは 15485863。
これがどのくらいの時間で実行されるのか知りたいとする。計測手段はいくつもあるが irb 上でサクッとできるなら,それはそれで嬉しい。

ではまず

gem update irb

で最新の irb をインストールしておこう。記事執筆時点(2020/12/23)での最新は 1.2.9 だ。

そして,

irb -r prime

で irb を起動する。
いや,もちろん

irb

で起動しておいて,

irb(main):001:0> require "prime"

とやってもいいのだが,面倒なので,使うライブラリーは -r オプションに渡したほうがいいだろう。

そして,

irb(main):001:0> measure

と打つと,式の評価時間を計測するモード2になる・・・はずなのだが,実はバージョン 1.2.8, 1.2.9 では何らかの手違いにより,LoadError が出るようになっている3
幸い,measure コマンドが使えるようにするためのプルリクエスト@elim さんにより出され,既に取り込まれている。

(2020-12-25 追記)irb 1.3.0(2020-12-24 リリース)にめでたく反映された。これで measure が使える。

現状では,仕方ないので

irb(main):001:0> IRB.conf[:MEASURE] = true

と打とう。こんなの覚えられないけど,覚えなくていい。次のバージョンでは measure でいけるようになるはずだ。(→ 追記:なった)

こうすると,irb 上で式を評価するたび,いちいち時間を測ってくれる。
ではさっそく:

irb(main):002:0> Prime.lazy.drop(999999).first
processing time: 7.395823s
=> 15485863

7.4 秒くらいだった。

計測モードをやめるには

irb(main):003:0> IRB.conf[:MEASURE] = false

とする。
measure コマンドが使えるようになったら,

irb(main):003:0> measure :off

でいけるようになるはずだ。

ところで,この手の速度(実行時間)計測では気をつけないといけないことがいろいろある。

irb の measure 機能は,デフォルトでは処理前後の時刻の差を取っているだけのようなので,CPU が他のことで忙しいときに計測すると大きめの値が出そう。
実行時間はさまざまな要因で揺れ動く。実際,さきの 100 万番目の素数は,もう一度測ったら 6.5 秒程度であった。
(2020-12-25 追記)なお,Prime はメモ化を使っているのか,irb を終了せずにもう一度やるとずっと短い時間で終了する。

計測結果が 7.395823s などと出ていても,有効数字はそんなに無い。表示される桁数が多いのは単に Float をそのまんま表示しているだけ。
まあおそらく小数第二位の桁(0.01 の桁)には意味が無いだろう。

だから,

irb(main):004:0> 1+1
processing time: 0.000282s
=> 2

とやって出てくる「0.000282s」という数字には全く意味が無い。「ホトンドゼロデスネー」としか言えない。
このような〈軽すぎる式評価〉の実行時間は,多数回実行させた時間を繰り返し数で割って求める必要がある。そうなるとベンチマークテストライブラリーの出番なわけで,irb なんかでやることではなくなってしまうだろう。

なお,筆者は試してないが,計測・表示の処理はカスタマイズできるようだ。
ユーザーのホームディレクトリーの .irbrc というファイルに,

IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |context, code, line_no, &block|
  # 云々
}

てな感じで記述すればいいらしい。
これで,例えば「結果表示は小数第一位までにするぞ」とかが可能になる。

具体的なことは irb のコミットメッセージをどうぞ:
https://github.com/ruby/irb/commit/3899eaf2e21fcb8b6c1ba3fdb1ac4ec8c9b4798f


  1. 他の言語の REPL を知らずに書いてますので各言語愛好者のマサカリ・オシカリを歓迎します。 

  2. 本家では「モード」という用語は使われていない。私がこの記事で仮にそう呼ぶだけ。 

  3. よく分からないけど,gem としてインストールした場合にこの問題が起こるようだ。(2020-12-25 追記)Ruby 3.0.0 にバンドルされる irb は問題ないらしい。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1