-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"when freedom patches fight, nobody wins" -@jeremy #138
Conversation
Use `JSON.generate` instead of `Object#to_json` The reasoning behind this is that `Object#to_json` is part of the [freedom]((https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/to_json.rb#L7-L19) [patching](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/json/encoding.rb#L305-L312) wars with `ActiveSupport`. This means that in Rails out of the box for Ruby 1.9+ (since json is part of stdlib), the asset pipeline will use the pure ruby `#to_json` method provided by `ActiveSupport`. This results in ~40% performance decrease.
great work tackling the issue ❤️ 👍 |
👍 |
1 similar comment
👍 |
btw, the commit message is great 😄 |
Guys, I'm all for this, but we had this before and ended up reverting it back. Here's the related issue: #86 |
So, could you all try this patch and run your real-life rails apps test suites against it? |
👍 |
The situation is actually quite complex, but I'll attempt to explain. TL;DR
❗ ❗ ❗ ❗ ❗ By the way, don't EVER require Here is why:
As you can see, they both define Here is what (currently) happens when you call ActiveSupport's
Here is what happens when you call JSON gem's
And this is what happens when you call
If you connect the dots, there are two major problems that prevents you from mixing JSON gem with ActiveSupport's JSON encoder:
There is one minor detail I haven't mentioned yet, the JSON gem comes in two versions – the pure Ruby version and the C extension, which is what MRI actually uses. The stuff I wrote above applies to the pure Ruby version. The C extension does more or less the same thing, except:
Which is why, on a good day, when you're calling The futureIn Rails 4.1, I'm working on a refactor of the encoding side to solve the aforementioned problems and use the By the way, if you have a Rails 4 app and would like to help test the new JSON encoder when it's ready, please shoot me an email at godfrey@caliper.io. It would be really helpful to be able to test this with real-world apps to tune compatibility and performance. So what should
|
thanks to @chancancode for taking on this hornets nest. 👏 |
See [1] for why this is not a good idea. As part of this refactor, circular reference protection in as_json has been removed and the corresponding error class has been deprecated. As discussed with @jeremy, circular reference error is considered programmer errors and protecting against it is out of scope for the encoder. This is again based on the excellent work by @sergiocampama in rails#11728. [1]: intridea/multi_json#138 (comment)
JSON.{dump,generate} offered by the JSON gem is not compatiable with Rails at the moment and can cause a lot of subtle bugs when passed certain data structures. This changed all direct usage of the JSON gem in internal Rails code to always go through AS::JSON.{decode,encode}. We also shouldn't be implementing `to_json` most of the time, and these occurances are replaced with an equivilent `as_json` implementation to avoid problems down the road. See [1] for all the juicy details. [1]: intridea/multi_json#138 (comment)
See [1] for why this is not a good idea. As part of this refactor, circular reference protection in as_json has been removed and the corresponding error class has been deprecated. As discussed with @jeremy, circular reference error is considered programmer errors and protecting against it is out of scope for the encoder. This is again based on the excellent work by @sergiocampama in rails#11728. [1]: intridea/multi_json#138 (comment)
* We use the Oj and multi_json gems, which makes Oj the default JSON parser. However, Rails' ActiveRecord::Base overrides this and uses the native JSON parser, which is slow. In our case we have two render() calls that represent nearly all cases where we ask ActiveRecord to serialize for us. In both cases we already have a hash (not a model object), and we always want JSON responses. So we can fix the performance problem simply by calling Oj.dump() ourselves, and passing the resulting JSON (instead of the hash) to render(). More gory details: * "ActiveRecord::Base.extend kills JSON performance": rails/rails#9212 * "when freedom patches fight, nobody wins": intridea/multi_json#138 (comment)
Use
JSON.generate
instead ofObject#to_json
The reasoning behind this is that
Object#to_json
is part of the [freedom]((https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/to_json.rb#L7-L19) patching wars withActiveSupport
. This means that in Rails out of the box for Ruby 1.9+ (since json is part of stdlib), the asset pipeline will usethe pure ruby
#to_json
method provided byActiveSupport
. This results in ~40% performance decrease.