シュッとやってみた文字列操作の処理速度比較

Rubyの話です。

f:id:tanaken0515:20190210092928p:plain

↓の記事を読んでいたら実行速度の話が出てきたので気になってシュッと調べてみました。 moneyforward.com

動作環境: Ruby 2.5.1

単一の文字列とのマッチ

正規表現は、あるパターンに従う文字列の集まりを指したいときには便利ですが、単一の文字列とのマッチに正規表現を使うのはやめましょう。文字列を使うべきです。実行速度がだいぶ違います。

比較してみた。文字列を10,000回splitするのを100回やって処理時間の平均値を出す。

irb(main):001:0> str = 'abcdefgh'
=> "abcdefgh"
irb(main):002:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str.split(/e/) } } }.sum / 100
=> 0.009860930000431836
irb(main):003:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str.split('e') } } }.sum / 100
=> 0.003988147991476581

文字列を使ったほうが2倍くらい速い

パターンマッチするか否かの真偽値

=~はマッチに成功した場合にただのtrueではなくマッチの位置を返します。制御構造の条件や論理演算で使っても問題になることはありませんが、これは欲しい情報に対して過多な情報で、そのために実行効率を落としています。真偽値を返すString#match?Regexp#match?に置き換えるだけで数倍速くなります。

比較してみた。パターンマッチの真偽値を10,000回出すのを、100回やって処理速度の平均値を出す。

irb(main):001:0> str = 'abcdefgh'
=> "abcdefgh"
irb(main):002:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str =~ /e/ } } }.sum / 100
=> 0.002607569007668644
irb(main):003:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str.match?(/e/) } } }.sum / 100
=> 0.0013666660047601908

String#match?を使ったほうが2倍くらい速い

完全一致

完全一致の場合は=~(もしくはmatch?)で比較するまでもなく、文字列にとって最も基本的な関係演算である==を使えばよいのです。

比較してみた。完全一致の真偽値を10,000回出すのを、100回やって処理速度の平均値を出す。

irb(main):001:0> str = 'abcdefgh'
=> "abcdefgh"
irb(main):002:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str =~ /\Aabcdefgh\z/ } } }.sum / 100
=> 0.0026517410040833057
irb(main):003:0> 100.times.map{ Benchmark.realtime{ 10000.times{ str == 'abcdefgh' } } }.sum / 100
=> 0.000976948984898627

==を使ったほうが3倍くらい速い

まとめ

記事内には他にも比較できそうなものがありましたが、今回はこの辺で。実際に数字を出してみると「ほぉ〜」となりますね。

ではまた。