Skip to content
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

Performance improvement: only reset and clear bindings when necessary #138

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

israel-lugo
Copy link
Contributor

Prepare shouldn't call Reset and ClearBindings unconditionally. The underlying C functions sqlite3_reset and sqlite3_clear_bindings functions are non-trivial and will cause some slow down.

Neither of them is necessary if the user already called them manually (e.g. to avoid holding a transaction open, or to allow large parameters to be freed early).

Also, ClearBindings is not necessary for statements that never had parameters bound to them.

I've implemented some benchmarks and measured before/after:

name                                                                old time/op  new time/op  delta
PrepareTransientAndFinalize/Select_constant-4                       4.94µs ± 1%  4.91µs ± 1%   -0.67%  (p=0.014 n=10+10)
PrepareTransientAndFinalize/Insert_constants-4                      4.91µs ± 1%  4.81µs ± 0%   -2.03%  (p=0.000 n=9+10)
PrepareTransientAndFinalize/Insert_with_params-4                    5.86µs ± 0%  5.64µs ± 1%   -3.77%  (p=0.000 n=10+10)
PreparePrimed/Select_constant-4                                      373ns ± 0%    13ns ± 0%  -96.63%  (p=0.000 n=10+10)
PreparePrimed/Insert_constants-4                                     376ns ± 0%    13ns ± 0%  -96.58%  (p=0.000 n=10+10)
PreparePrimed/Insert_with_params-4                                   380ns ± 0%    13ns ± 0%  -96.62%  (p=0.000 n=9+8)
PrepareBindAndSelect/Select_constant-4                               775ns ± 0%   589ns ± 1%  -23.93%  (p=0.000 n=9+10)
PrepareBindAndSelect/Select_constant,_explicit_reset-4               953ns ± 0%   584ns ± 1%  -38.71%  (p=0.000 n=10+9)
PrepareBindAndSelect/Select_int_param_directly-4                    1.10µs ± 0%  1.11µs ± 0%   +1.16%  (p=0.000 n=10+8)
PrepareBindAndSelect/Select_int_param_directly,_explicit_reset-4    1.24µs ± 0%  1.10µs ± 0%  -11.04%  (p=0.000 n=10+10)
PrepareBindAndSelect/Select_from_table-4                            2.24µs ± 0%  2.29µs ± 0%   +1.97%  (p=0.000 n=10+10)
PrepareBindAndSelect/Select_from_table,_explicit_reset_and_clear-4  2.65µs ± 0%  2.44µs ± 0%   -8.08%  (p=0.000 n=10+10)

Note the massive improvement for Prepare when already primed. Also a significant improvement for Prepare + Bind + Select when the user is explicitly doing Reset and/or Reset+ClearBindings. These really add up after a few hundred thousand operations.

The +1% worsening on SELECT $f1 is likely just background variation.

Prepare shouldn't call Reset and ClearBindings unconditionally. The
underlying C functions sqlite3_reset and sqlite3_clear_bindings
functions are non-trivial and will cause some slow down.

Neither of them is necessary if the user already called them manually
(e.g. to avoid holding a transaction open, or to allow large parameters
to be freed early).

Also, ClearBindings is not necessary for statements that never had
parameters bound to them.

Benchmarks:

name                                                                old time/op  new time/op  delta
PrepareTransientAndFinalize/Select_constant-4                       4.94µs ± 1%  4.91µs ± 1%   -0.67%  (p=0.014 n=10+10)
PrepareTransientAndFinalize/Insert_constants-4                      4.91µs ± 1%  4.81µs ± 0%   -2.03%  (p=0.000 n=9+10)
PrepareTransientAndFinalize/Insert_with_params-4                    5.86µs ± 0%  5.64µs ± 1%   -3.77%  (p=0.000 n=10+10)
PreparePrimed/Select_constant-4                                      373ns ± 0%    13ns ± 0%  -96.63%  (p=0.000 n=10+10)
PreparePrimed/Insert_constants-4                                     376ns ± 0%    13ns ± 0%  -96.58%  (p=0.000 n=10+10)
PreparePrimed/Insert_with_params-4                                   380ns ± 0%    13ns ± 0%  -96.62%  (p=0.000 n=9+8)
PrepareBindAndSelect/Select_constant-4                               775ns ± 0%   589ns ± 1%  -23.93%  (p=0.000 n=9+10)
PrepareBindAndSelect/Select_constant,_explicit_reset-4               953ns ± 0%   584ns ± 1%  -38.71%  (p=0.000 n=10+9)
PrepareBindAndSelect/Select_int_param_directly-4                    1.10µs ± 0%  1.11µs ± 0%   +1.16%  (p=0.000 n=10+8)
PrepareBindAndSelect/Select_int_param_directly,_explicit_reset-4    1.24µs ± 0%  1.10µs ± 0%  -11.04%  (p=0.000 n=10+10)
PrepareBindAndSelect/Select_from_table-4                            2.24µs ± 0%  2.29µs ± 0%   +1.97%  (p=0.000 n=10+10)
PrepareBindAndSelect/Select_from_table,_explicit_reset_and_clear-4  2.65µs ± 0%  2.44µs ± 0%   -8.08%  (p=0.000 n=10+10)

Note the massive improvement for Prepare when already primed. Also a
significant improvement for Prepare + Bind + Select when the user is
explicitly doing Reset and/or Reset+ClearBindings.

The +1% worsening on SELECT $f1 is likely just background variation.
@israel-lugo israel-lugo changed the title Only reset and clear bindings when necessary Performance improvement: only reset and clear bindings when necessary Nov 10, 2022
@israel-lugo
Copy link
Contributor Author

@AdamSLevy could you please take a look, at your convenience?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant