What is the fastest way to render json in rails
I'm optimizing some slow transactions in our Rails application and a I see significant time spent rendering JSON views:
Rendered welcome/index.json.rabl (490.5ms)
Completed 200 OK in 1174ms (Views: 479.6ms | ActiveRecord: 27.8ms)
Assuming that the API call is returning exactly the data it needs to return, What is the fastest way to render JSON in rails?
We are using Rabl because of the ability to share code easily, but we aren't tied to it.
Currently oj seems to be the fastest renderer - beating yajl (according to the oj author's comparison).
Oj is used by default in the latest multi_json (and rails uses mutli_json by default), so swapping to oj should be as simple as adding the following to your Gemfile:
# Gemfile
gem "oj"
Then each time you call render, it will now use oj.
render :json => { ... } # uses multi_json which uses oj
Oj also provides additional specific interfaces, if you want even more performance, but sticking to multi_json makes it easier to swap out gems in the future.
Note that if you have any { ... }.to_json
calls - these will not be upgraded to use oj unless you call Oj.mimic_JSON
in an initializer.
Rails 3 uses multi_json, but it only uses it for json decoding, not encoding. Json encoding/rendering/generation uses ActiveSupport JSON library's to_json
method, therefore is always slow (even if you uses Oj gem).
You can explicitly rendering using multi_json by doing:
render :json => MultiJson.dump(@posts)
Or you can try rails-patch-json-encode gem (by me) which will use multi_json by default. It will affect all build-in to_json
methods, so make sure all the tests passes.
Rabl uses multi_json
for compatibility across platforms and doesn't use the quite fast Yajl library by default. Rabl's config documentation explains the solution:
# Gemfile
gem 'yajl-ruby', :require => "yajl"
In the event that still isn't performant enough, you might want to explore a different JSON serializer like oj. You could also instrument your render and see where the bottleneck exists.