ぶていのログでぶログ

思い出したが吉日

rfコマンドv1.16.0をリリースした

前回の更新記事はこちら。 rfコマンドv1.16.0をリリースした。主にbug fix

github.com

🏕 Features

実は実行速度が6倍くらい速くなっていた

v1.15.0の更新記事に書き忘れてしまったのだが、v1.15.0は過去のバージョンに比べて6倍くらい早くなっていた。 1MB、104334行あるテキストファイルで比較してみると違いがわかりやすい。

# テストで使うテキストファイル
$ ls -lah /usr/share/dict/american-english
-rw-r--r-- 1 root root 962K Jan 20  2022 /usr/share/dict/american-english
$ wc /usr/share/dict/american-english
104334 104334 985084 /usr/share/dict/american-english

# v1.14.0
$ rf --version
rf 1.14.0 (mruby 3.2.0 9e50d67)

$ time rf -q -g hello /usr/share/dict/american-english

________________________________________________________
Executed in   31.80 secs    fish           external
   usr time   30.13 secs  375.00 micros   30.13 secs
   sys time    0.96 secs    0.00 micros    0.96 secs

# v1.15.0
$ rf --version
rf 1.15.0 (mruby 3.2.0 9e50d67)

$ time rf -q -g hello /usr/share/dict/american-english

________________________________________________________
Executed in    5.20 secs    fish           external
   usr time    3.41 secs  156.00 micros    3.41 secs
   sys time    1.68 secs  171.00 micros    1.68 secs

圧倒的に改善されている。 なぜ、ここまで速くなったのかというと、なんとビルド時に最適化オプションをつけ忘れていたというオチ。。 最適化オプションをつけただけでこんなに速くなるんですね。。コンパイラすごい。

ちなみに、grepは1secどころか2msすらかからないのですごい。。。

$ time grep -q hello /usr/share/dict/american-english

________________________________________________________
Executed in    1.25 millis    fish           external
   usr time    1.04 millis  199.00 micros  840.00 micros
   sys time    0.22 millis  217.00 micros    0.00 micros

TAB(0x09)がバイナリファイル判定されていた

TABが含まれたファイル(e.g. tsvファイル)をrfに食わせるとバイナリファイルとして判定されていた。

$ echo -e "a\tb" | rf _
Binary file matches.

これは意図した挙動ではないので修正した。

MRB_IREP_LVAR_MERGE_LIMIT を最大まで増やした

最近知ったのだけど、mrubyではローカル変数は255個以上定義できない。 そして、Bindingクラスのインスタンスではローカル変数はデフォルトでは50個以上定義できないようになっている。 これが何が困るかというと、例えば、rfにおいて各行を足し合わせるみたいな処理をするときに、51行以上のファイルがあるとこの制約にかかってしまう。

# すべての行を足し合わせて最後に合計値を出力
$ seq 1 50 | rf -q 's+=_; at_exit{ puts s }'
Error: too many local variables for binding (mruby limitation)

# 49行なら正しく出力される
$ seq 1 49 | rf -q 's+=_; at_exit{ puts s }'
1225

これはとても困る。。 これを緩和するにはMRB_IREP_LVAR_MERGE_LIMITを増やせばいいということがわかった。

github.com

ただ、先のローカル変数の定義数の最大値も関係しているのか240が最大値になっている。 ソースを改変せずに定義数を増やす方法がわからなかったので、一旦240にしてある。

ちなみに、この問題はグローバル変数を使うことで回避できる。

$ seq 1 240 | rf -q 's+=_; at_exit{ puts s }'
Error: too many local variables for binding (mruby limitation)

$ seq 1 240 | rf -q '$s+=_; at_exit{ puts $s }'
28920

しかし、変数に名に $ をつけるのはタイプ数が増えるし、シェルにおいてはシェル変数として解釈されないようにエスケープなどしなくてはならず、個人的にはイマイチなのでなんとか解決策を見つけたい。