Ruby 2.4 で CGI.unescape が高速化されていた
久しぶりに ruby をいじる機会があったので、備忘的に。
URL encode された文字列を decode したいのだけど、Ruby 2.1 の URI.decode
だと遅すぎる!
というのをなんとか解決できないかと調べていました。
ベンチマークコード
似たようなことをやってくれるメソッドが複数あったので、とりあえずベンチとってみる。
require 'benchmark' require 'uri' require 'cgi' encoded = '%7B%22hoge%22%3A%7B%22foo%22%3A%22bar%22%2C%22hoo%22%3A%22baz%22%7D%7D' # => {"hoge":{"foo":"bar","hoo":"baz"}} def manytimes 100000.times { yield } if block_given? end Benchmark.bmbm do |bm| bm.report("URI.decode") { manytimes { URI.decode encoded } } bm.report("URI.decode_www_form_component") { manytimes { URI.decode_www_form_component encoded } } bm.report("CGI.unescape") { manytimes { CGI.unescape encoded } } end
Ruby 2.1
$ ruby --version ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-darwin15.0] $ ruby decode_bench.rb Rehearsal ----------------------------------------------------------------- URI.decode 2.360000 0.020000 2.380000 ( 2.404751) URI.decode_www_form_component 1.270000 0.010000 1.280000 ( 1.467851) CGI.unescape 1.480000 0.020000 1.500000 ( 1.578028) -------------------------------------------------------- total: 5.160000sec user system total real URI.decode 2.570000 0.030000 2.600000 ( 2.729236) URI.decode_www_form_component 1.170000 0.010000 1.180000 ( 1.189314) CGI.unescape 1.510000 0.010000 1.520000 ( 1.577981)
遅いし obsolete だし、URI.decode はやめておいた方がよさそうだ。 singleton method URI.decode (Ruby 2.4.0)
URI.decode_www_form_component
を使うのがいいのかな?
Ruby 2.4
試しに Ruby 2.4 でベンチとってみたら、思わぬ結果になった。
$ ruby --version ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15] $ ruby decode_bench.rb Rehearsal ----------------------------------------------------------------- URI.decode 2.290000 0.010000 2.300000 ( 2.334818) URI.decode_www_form_component 1.280000 0.020000 1.300000 ( 1.330829) CGI.unescape 0.120000 0.000000 0.120000 ( 0.133207) -------------------------------------------------------- total: 3.720000sec user system total real URI.decode 2.560000 0.030000 2.590000 ( 2.859363) URI.decode_www_form_component 1.270000 0.010000 1.280000 ( 1.329829) CGI.unescape 0.120000 0.000000 0.120000 ( 0.127875)
CGI.unescape
が10倍以上速くなっている。
Ruby 2.4 から CGI モジュールのいくつかのメソッドが C拡張として実装されたらしい。
escape/unescape, escapeHTML/unescapeHTML 辺りが対象かな?
ruby/escape.c at trunk · ruby/ruby · GitHub
というわけで
URL decode したい時は Ruby 2.4 にして CGI.unescape
を使うと速いよ!ということでした。