-
Notifications
You must be signed in to change notification settings - Fork 345
Make JSON::Parser initialization faster #512
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
Here's the benchmark code: On my machine:
|
cbd1224
to
32a2f66
Compare
😮 |
@luke-gru Can you keep the current indent style? We can view only code changes with https://github.com/flori/json/pull/512/files?w=1. But style changes may causes code-conflict when I backport this to ruby/ruby. |
HI @hsbt, for the JSON init function, it's a bit subtle but I had to remove the check EDIT: my ragel is |
I know that. I say |
877eed0
to
b6185b5
Compare
Understood, sorry for the confusion. Just updated it. |
Remove calls to rb_funcall, don't go back in to interpreter if not necessary. Also remove unnecessary calls to rb_respond_to(val) when val is nil. Speedup of JSON.parse when parsing small amount of data in a tight loop is up to 40%.
b6185b5
to
e525bed
Compare
ext/json/ext/parser/parser.rl
Outdated
if (json->decimal_class != Qnil) { | ||
if (rb_respond_to(json->decimal_class, i_try_convert)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems indents broken.
If you want to keep the indent of the following block,
if (json->decimal_class != Qnil) { | |
if (rb_respond_to(json->decimal_class, i_try_convert)) { | |
if (NIL_P(json->decimal_class)) { | |
/* use the default conversion */ | |
} else if (rb_respond_to(json->decimal_class, i_try_convert)) { |
ext/json/ext/parser/parser.h
Outdated
#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key)) | ||
extern VALUE rb_hash_has_key(VALUE hash, VALUE key); | ||
|
||
#define hash_option_given_p(opts, key) (RTEST(rb_hash_has_key(opts, key))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this name need to be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a problem with using a non public API?
When I tried before, I created my own function with the same effect. #481
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Watson1978 I wasn't aware of your PR, I should have checked the other PRs more thoroughly before coding up my solution. Yours is better IMO with using only public API, and also making changes to JSON.generate
. The only thing that my PR has that's different in the initialize function is that it checks if the hash is empty before going through all the option checks, which yours could add if you want. I also think your other PR (#454) could be merged with the changes in #481.
I'm fine with closing my PR now if yours gets a second look. However if you're busy I'll just take some ideas from your PR and add to mine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a problem with using a non public API?
Yes, that is not respecting the API and will likely break. Also it would likely not work e.g. on truffleruby needlessly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, fixed
I accept this proposal. But I'm not familiar with C internals. I requested additional review for @nobu |
Yeah, I'll try to get this updated some time today. Thanks for the reminder 😄 |
I finally got around to working on this. I added a 2nd commit so you can see the changes from the first. When approved, I will squash them. |
Extracted from: ruby#512 Use `rb_hash_lookup2` to check for hash key existence instead of going through `rb_funcall`. Co-Authored-By: lukeg <luke.gru@gmail.com>
Extracted from: ruby#512 Use `rb_hash_lookup2` to check for hash key existence instead of going through `rb_funcall`. Co-Authored-By: lukeg <luke.gru@gmail.com>
Extracted from: ruby/json#512 Use `rb_hash_lookup2` to check for hash key existence instead of going through `rb_funcall`. ruby/json@43835a0d13 Co-Authored-By: lukeg <luke.gru@gmail.com>
Closes: ruby#512 Co-Authored-By: lukeg <luke.gru@gmail.com>
Nevermind. After looking at it with fresh eyes, it was actually quite simple. All the parts of this PR have now been merged. |
…s nil Closes: ruby/json#512 ruby/json@d882a45d82 Co-Authored-By: lukeg <luke.gru@gmail.com>
…s nil Closes: ruby/json#512 ruby/json@d882a45d82 Co-Authored-By: lukeg <luke.gru@gmail.com>
…s nil Closes: ruby/json#512 ruby/json@d882a45d82 Co-Authored-By: lukeg <luke.gru@gmail.com>
Remove calls to rb_funcall, don't go back in to interpreter if not necessary. Also remove unnecessary calls to rb_respond_to(val) when val is nil. Speedup of JSON.parse when parsing small amount of data in a tight loop is up to 40%.