-
Notifications
You must be signed in to change notification settings - Fork 420
Make to_json twice as fast as it used to be #177
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
Conversation
7dcabed
to
5f73c2d
Compare
@shuheiktgw Thanks for the pull request @bf4 do you mind taking a look into this? |
@shishirmk I think there's a lot to discuss in this PR. Firstly, is the argument that the first time the method is called is twice as fast? If so, I don't think that's a useful benchmark. Most applications will live to have the method called more than that. In any case, I think it may be better to tell end users they can put a call to_json in an initializer to eagerly evaluate the method after all the relevant gems are required. For what it's worth, this pattern comes from a perf PR to ActiveModelSerializers that still holds up rails-api/active_model_serializers#233 The rest of the changes in this PR need a discussion of cost benefit analysis, including taking into account that the original PR was merged without a test suite, but was tested otherwise. The various methods removed in this PR are critical to configuring and debugging the behavior. I would use it in #135 |
On my machine, a MBP running Ruby 2.4.1 I run the bench against master and get about 0.28ms each run and against make_to_json_fast about 0.11 ms each run. But, if I change the benchmark to run to_json just once, I get the same 0.03 ms on each branch. require 'spec_helper'
describe FastJsonapi::MultiToJson do
include_context 'movie class'
before(:all) { GC.disable }
after(:all) { GC.enable }
describe 'self.to_json' do
it do
+ FastJsonapi::MultiToJson.to_json movie
second = Benchmark.measure { FastJsonapi::MultiToJson.to_json movie }.real * 1000
print 'to_json: '
puts "#{second} ms"
end
end
end Let's rewrite the benchmark to use
require 'spec_helper'
describe FastJsonapi::MultiToJson do
include_context 'movie class'
describe 'self.to_json' do
it do
n = 1_000
Benchmark.bmbm do |x|
x.report('to_json') {
i = 0
while i < n
FastJsonapi::MultiToJson.to_json movie
i += 1
end
}
end
end
end
end Here are the outputs against each branch. I'm not going to label which branch is which 'cause they're the same :)
Or with benchmark-ips
code is require 'spec_helper'
require 'benchmark/ips'
describe FastJsonapi::MultiToJson do
include_context 'movie class'
describe 'self.to_json' do
it do
Benchmark.ips do |x|
x.report('to_json') do |n|
i = 0
while i < n
FastJsonapi::MultiToJson.to_json movie
i += 1
end
end
end
end
end
end |
@shuheiktgw I commented above |
@bf4 Thank you so much for your comments! You are absolutely right if you take a benchmark multiple time the result will be the same since the difference appears only for the first time that Even if this PR does not improve performance, I personally believe that I can simply |
I don’t see the benefit of removing the logger or the current behavior of how the methods are defined. Is it aesthetic?
B mobile phone
… On Apr 22, 2018, at 4:43 AM, Shuhei Kitagawa ***@***.***> wrote:
@bf4 Thank you so much for your comments! You are absolutely right if you take a benchmark multiple time the result will be the same since the difference appears only for the first time that to_json is called.
Even if this PR does not improve performance, I personally believe that I can simply to_json method by using class_eval. What would you think if I make back some logging features I removed?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
@shuheiktgw Given this discussion, I think you should rename the PR to describe what you want to do with it. |
I found the current implementation of
to_json
can be slow since it definesto_json
method dynamically first time the method is called. So I useclass_eval
instead and change to define the method when class itself is evaluated. As a resultto_json
method bacame two times faster (from0.4819999448955059
ms to0.2079999540001154
ms) and the class became much simpler!Below is the test code I used to check the performance.