前回の記事はこちら。 前回に続いてついにYAMLの色つけ出力に対応した!やったぜ。 また、JSONの色つけ出力も改善し、階層ごとにObject(HASH)のキーの色を変えるようにした。 これで視認性が上がるはず。
以下、変更点の詳細
🏕 Features
- Fix CI error on macos-14 by @buty4649 in https://github.com/buty4649/rf/pull/215
- Update mruby-yyjson to v1.7.0 by @buty4649 in https://github.com/buty4649/rf/pull/220
- Use mruby-rapidyaml insted of mruby-yaml by @buty4649 in https://github.com/buty4649/rf/pull/221
- Make test case stricter by @buty4649 in https://github.com/buty4649/rf/pull/222
- Add colorize support for YAML filter by @buty4649 in https://github.com/buty4649/rf/pull/223
mruby-yamlに変わってmruby-rapidyamlを使うようにした
YAMLの色つけ出力を行うために、mruby-rapidyamlという新しいmgemを作った。
mruby-yamlをforkしてもよかったのだが、せっかくなので1から作ろうと思いたちこれを作った。 …が、結構苦労したのでそれは別の記事で書く予定。。
色つけ出力ができるようになったという効果もあったのだが、rapidyamlは名前の通り高速性も売りにしていて、その恩恵にあやかり、rfも高速でYAMLをパースできるようになった! 手元の環境で、73MB程度のYAML(後述)の読み込みをrf v1.23.0、rf v1.22.0と参考にyq v4.43.1、CRuby v3.3.4のYAMLライブラリで比較してみた。
❯ ls -lah large_file.yaml -rw-r--r-- 1 buty4649 buty4649 74M Aug 18 23:15 large_file.yaml ❯ hyperfine --warmup 3 --input large_file.yaml 'mise exec rf@1.23.0 -- rf -y -qs _' 'mise exec rf@1.22.0 -- rf -y -qs _' 'yq null' 'ruby -ryaml -e YAML.load\(\$stdin.read\)' Benchmark 1: mise exec rf@1.23.0 -- rf -y -qs _ Time (mean ± σ): 983.9 ms ± 4.9 ms [User: 776.4 ms, System: 139.6 ms] Range (min … max): 977.5 ms … 991.5 ms 10 runs Benchmark 2: mise exec rf@1.22.0 -- rf -y -qs _ Time (mean ± σ): 2.382 s ± 0.029 s [User: 1.852 s, System: 0.335 s] Range (min … max): 2.308 s … 2.422 s 10 runs Benchmark 3: yq null Time (mean ± σ): 2.984 s ± 0.054 s [User: 3.766 s, System: 0.267 s] Range (min … max): 2.920 s … 3.080 s 10 runs Benchmark 4: ruby -ryaml -e YAML.load\(\$stdin.read\) Time (mean ± σ): 8.496 s ± 0.060 s [User: 7.350 s, System: 0.373 s] Range (min … max): 8.424 s … 8.617 s 10 runs Summary mise exec rf@1.23.0 -- rf -y -qs _ ran 2.42 ± 0.03 times faster than mise exec rf@1.22.0 -- rf -y -qs _ 3.03 ± 0.06 times faster than yq null 8.63 ± 0.07 times faster than ruby -ryaml -e YAML.load\(\$stdin.read\)
rf v1.22.0は2.42sだったのが、v1.23.0では0.983s(983ms)になった!約2.46倍早くなったすごい! これだけでもmruby-rapidyamlを実装してよかったとおもう。
おまけ: 巨大なYAMLファイルを生成するスクリプト
テストにつかった巨大なYAMLファイルを生成するスクリプト。 ChatGPTに作ってもらったのだが、出力サイズを10MBと指定しても誤差がひどくて74MBのファイルが生成された。
require 'yaml' # 3階層のダミーデータを生成するための関数 def generate_large_data(entry_count) data = {} entry_count.times do |i| nested_data = {} 10.times do |j| inner_data = {} 10.times do |k| inner_data["key_#{i}_#{j}_#{k}"] = "value_" + ("a" * 50) # さらに内側のキーと値 end nested_data["key_#{i}_#{j}"] = inner_data end data["key_#{i}"] = nested_data end data end # 大きなYAMLファイルを生成する def create_large_yaml_file(filename, size_in_mb) entry_count = (size_in_mb * 1024 * 1024) / 1040 # 1エントリのサイズが約1040バイトと仮定 data = generate_large_data(entry_count) File.open(filename, 'w') do |file| file.write(YAML.dump(data)) end end # 10MBのYAMLファイルを作成 create_large_yaml_file('large_file.yaml', 10)
rfのテストを厳格化した
rfではrfコマンドの実行してその出力が意図した通りかをチェックしている。 この出力のマッチャーの指定が今までmatchだったのをeqにした。 該当のコードは以下のような感じ。
# 変更前 expect(last_command_started.output).to match expect_output # 変更後 expect(last_command_started.output).to eq expect_output
matchマッチャーを使うと正規表現を使って判定するようで意図しないテストになっていた。 そのため、厳格にチェックするためにeqに変更した。 ただしこれだとバージョンごとに出力が変わる項目などのテストがとても煩雑になるので、expect_outputがRegexpのインスタンスの場合は今まで通りmatchを使うようにした。