-
Notifications
You must be signed in to change notification settings - Fork 548
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
Improve performance to call Mysql2::Result#each and Mysql2::Result#fields #1046
Conversation
By convert C-string to Ruby string ID each time, it will take a slightly time to call method each time. This patch will catch the Ruby string ID to cut off the time. * Before ``` Warming up -------------------------------------- query 886.000 i/100ms each 67.339k i/100ms fields 195.612k i/100ms Calculating ------------------------------------- query 9.385k (± 4.5%) i/s - 46.958k in 5.016539s each 901.633k (± 0.2%) i/s - 4.512M in 5.003951s fields 3.779M (± 0.2%) i/s - 18.974M in 5.021533s ``` * After ``` Warming up -------------------------------------- query 845.000 i/100ms each 86.916k i/100ms fields 231.527k i/100ms Calculating ------------------------------------- query 9.553k (± 2.0%) i/s - 48.320k in 5.059947s each 1.133M (± 0.3%) i/s - 5.736M in 5.062606s fields 6.319M (± 0.1%) i/s - 31.719M in 5.019960s ```
ext/mysql2/result.c
Outdated
block = Qfalse; | ||
if (rb_block_given_p()) { | ||
block = Qtrue; | ||
} |
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.
Great explanation that actually capturing the block will generate a Proc object that is never called!
To really clarify this code, I suggest a deeper change:
-
Add a comment above
rb_scan_args
that says something like "A block can be passed to this method, but since we don't call the block directly from C, we don't need to capture it into a variable here with the "&" scan arg" -
Remove the
block
variable entirely. -
Replace
args.block_given = block;
on line 890 withargs.block_given = rb_block_given_p()
(Adjust the data type of args.block_given
to match the return value of rb_block_given_p()
if needed)
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.
This is great work, thank you! One comment in the review. |
2638717
to
f7b0db4
Compare
`rb_scan_args(argc, argv, "01&", ...)` will generate `Proc` object from block. However, the object has used to only check whether block was given. To remove redundant object generating, this patch will use `rb_block_given_p()` to check whether block was given. * Before ``` Warming up -------------------------------------- query 845.000 i/100ms each 86.916k i/100ms fields 231.527k i/100ms Calculating ------------------------------------- query 9.553k (± 2.0%) i/s - 48.320k in 5.059947s each 1.133M (± 0.3%) i/s - 5.736M in 5.062606s fields 6.319M (± 0.1%) i/s - 31.719M in 5.019960s ``` * After ``` Warming up -------------------------------------- query 864.000 i/100ms each 106.916k i/100ms fields 251.255k i/100ms Calculating ------------------------------------- query 9.457k (± 3.8%) i/s - 47.520k in 5.032949s each 1.550M (± 0.3%) i/s - 7.805M in 5.037029s fields 6.233M (± 0.1%) i/s - 31.407M in 5.039049s ```
f7b0db4
to
a734989
Compare
This PR will reduce the time to call Mysql2::Result#each and Mysql2::Result#fields.
If table records are small enough, the performance will improve as following.
This patch will catch the Ruby string ID to cut off the time.
rb_scan_args(argc, argv, "01&", ...)
will generateProc
object from block. However, the object has used to only check whether block was given. To remove redundant object generating, this patch will userb_block_given_p()
to check whether block was given.Environment
Before changing
After changing
Benchmarks