読者です 読者をやめる 読者になる 読者になる

Rails の to_json を 13 倍速くする方法

http://shugo.net/jit/20060715.html
先日、ちょっとした Rails アプリを作っていたのですが、JSON で出力する部分がやたらと遅くて困ってました。で、軽く調べてみたら ActiveSupport の String#to_json がやたらと重い!そういえば前田さんも遅い云ってたよな、と思って上記 URL で書いてある String#to_json に変更したところ、なんと約 13 倍も速くなるという驚きの結果に!!!
というわけで、Rails で JSON な API を提供している人は割と上記 String#to_json の変更が必須かと。本家にとりこまれないかなー。
あとベンチマークはこんな感じで。Benchmark::Runner は自作のを使ってます。

#!/usr/bin/env ruby
require 'benchmark/runner'
require 'open-uri'
require 'rubygems'
require 'active_support'

class String
  JSON_ESCAPED = {
     "\010" =>  '\b',
     "\f" =>    '\f',
     "\n" =>    '\n',
     "\r" =>    '\r',
     "\t" =>    '\t',
     '"' =>     '\"',
     '\\' =>    '\\\\'
  }

  def fast_to_json
    return '"' + gsub(/[\010\f\n\r\t"\\]/) { |s|
      JSON_ESCAPED[s]
    }.gsub(/([\xC0-\xDF][\x80-\xBF]|
             [\xE0-\xEF][\x80-\xBF]{2}|
             [\xF0-\xF7][\x80-\xBF]{3})+/ux) { |s|
      s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&')
    } + '"'
  end
end

class JsonBench < Benchmark::Runner
  def setup
    @source = open('http://www.hatena.ne.jp/').read
  end

  def activesupport_to_json
    @source.to_json
  end

  def fast_to_json
    @source.fast_to_json
  end
end

JsonBench.run(5)

結果

                           user     system      total        real
fast_to_json           0.010000   0.230000   0.240000 (  0.242278)
activesupport_to_json  0.340000   2.910000   3.250000 (  3.255585)

ライド・オン・Rails Ruby on Railsを徹底攻略
吉田 和弘 馬場 道明
ソフトバンククリエイティブ (2006/06/30)