Skip to content

core/sqlite: speedup cache write using multi-vealue sqlite inserts - #132

Merged
karlicoss merged 1 commit into
masterfrom
speedup
Aug 21, 2026
Merged

core/sqlite: speedup cache write using multi-vealue sqlite inserts#132
karlicoss merged 1 commit into
masterfrom
speedup

Conversation

@karlicoss

Copy link
Copy Markdown
Owner

sqlite3.executemany() repeatedly steps and resets a single-row statement for every cached item.

Emit one multi-row INSERT per Cachew chunk instead, splitting at SQLITE_LIMIT_VARIABLE_NUMBER and caching SQL by batch size.

This preserves one row per item and atomic publication while reducing write overhead.

Benchmarks:

$ uv run --group testing --python /home/karlicos/.local/share/uv/python/cpython-3.14.4-linux-x86_64-gnu/bin/python3.14 -m pytest_benchmark compare .benchmarks/Linux-CPython-3.14-64bit/0008_sqlite3-backend.json .benchmarks/Linux-CPython-3.14-64bit/0009_sqlite-multivalue.json -k 'test_05_real_dump_e2e and sqlite' --between=mean,median --time-unit=ms --name=short

--------------------------------- benchmark 'datetimes-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                       0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
--------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-datetimes-100k]      269.2184   246.2861     -8.5%     266.2679     246.1437     -7.6%
--------------------------------------------------------------------------------------------------------------------------

---------------------------------- benchmark 'nested-dataclass-05_dump_e2e': 1 tests, 2 sources ---------------------------------
Name (time in ms)                                              0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
---------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-nested-dataclass-100k]      183.3674   154.5616    -15.7%     183.3567     153.9058    -16.1%
---------------------------------------------------------------------------------------------------------------------------------

--------------------------------- benchmark 'primitive-int-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                           0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-primitive-int-100k]       71.8638    45.1905    -37.1%      72.0352      45.2104    -37.2%
------------------------------------------------------------------------------------------------------------------------------

--------------------------------- benchmark 'union-dataclass-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                             0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
--------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-union-dataclass-100k]      166.0094   133.0951    -19.8%     165.6174     132.8846    -19.8%
--------------------------------------------------------------------------------------------------------------------------------

Legend:
  Cyan: reference source for comparison. Green: improvement, Red: regression.
  Δ: percentage change from reference source.

`sqlite3.executemany()` repeatedly steps and resets a single-row statement for every cached item.

Emit one multi-row INSERT per Cachew chunk instead, splitting at `SQLITE_LIMIT_VARIABLE_NUMBER` and caching SQL by batch size.

This preserves one row per item and atomic publication while reducing write overhead.

Benchmarks:
```
$ uv run --group testing --python /home/karlicos/.local/share/uv/python/cpython-3.14.4-linux-x86_64-gnu/bin/python3.14 -m pytest_benchmark compare .benchmarks/Linux-CPython-3.14-64bit/0008_sqlite3-backend.json .benchmarks/Linux-CPython-3.14-64bit/0009_sqlite-multivalue.json -k 'test_05_real_dump_e2e and sqlite' --between=mean,median --time-unit=ms --name=short

--------------------------------- benchmark 'datetimes-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                       0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
--------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-datetimes-100k]      269.2184   246.2861     -8.5%     266.2679     246.1437     -7.6%
--------------------------------------------------------------------------------------------------------------------------

---------------------------------- benchmark 'nested-dataclass-05_dump_e2e': 1 tests, 2 sources ---------------------------------
Name (time in ms)                                              0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
---------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-nested-dataclass-100k]      183.3674   154.5616    -15.7%     183.3567     153.9058    -16.1%
---------------------------------------------------------------------------------------------------------------------------------

--------------------------------- benchmark 'primitive-int-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                           0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-primitive-int-100k]       71.8638    45.1905    -37.1%      72.0352      45.2104    -37.2%
------------------------------------------------------------------------------------------------------------------------------

--------------------------------- benchmark 'union-dataclass-05_dump_e2e': 1 tests, 2 sources ----------------------------------
Name (time in ms)                                             0008 Mean  0009 Mean     ΔMean  0008 Median  0009 Median   ΔMedian
--------------------------------------------------------------------------------------------------------------------------------
05_real_dump_e2e[cachew-real-sqlite-union-dataclass-100k]      166.0094   133.0951    -19.8%     165.6174     132.8846    -19.8%
--------------------------------------------------------------------------------------------------------------------------------

Legend:
  Cyan: reference source for comparison. Green: improvement, Red: regression.
  Δ: percentage change from reference source.
```
@karlicoss
karlicoss merged commit ec73350 into master Aug 21, 2026
13 checks passed
@karlicoss
karlicoss deleted the speedup branch August 21, 2026 00:06
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