Skip to content

Default SQLite connections to WAL#405

Draft
JanJakes wants to merge 1 commit into
trunkfrom
wal
Draft

Default SQLite connections to WAL#405
JanJakes wants to merge 1 commit into
trunkfrom
wal

Conversation

@JanJakes
Copy link
Copy Markdown
Member

@JanJakes JanJakes commented May 26, 2026

What changed

  • Default new SQLite connections to journal_mode = WAL.
  • Apply synchronous = NORMAL when WAL is the effective journal mode.
  • Keep explicit SQLITE_JOURNAL_MODE and SQLITE_SYNCHRONOUS overrides wired through the WordPress plugin connection paths, including initial installation.
  • Add focused connection setup tests for the WAL default and override behavior.

Why

WAL improves read/write concurrency for SQLite-backed WordPress installs. synchronous = NORMAL avoids the extra transaction fsync cost that hurts throughput in WAL mode, while rollback-journal modes keep SQLite's default durability unless explicitly configured.

Benchmark summary

A local 16-worker concurrent WordPress-shaped driver workload compared latest trunk using DELETE/FULL against latest trunk plus this change using WAL/NORMAL. WAL/NORMAL increased median throughput by about 3.2x on public 90R/10W traffic and about 4.1x on write-burst 70R/30W traffic, while cutting p95 latency by about 82-93% with zero SQLITE_BUSY or other errors.

Validation

  • ./vendor/bin/phpunit -c ./phpunit.xml.dist tests/WP_SQLite_Connection_Tests.php
  • composer run test in packages/mysql-on-sqlite
  • composer run check-cs
  • git diff --check
  • Local concurrent traffic benchmark against latest trunk

Configure new SQLite connections to use WAL by default and apply synchronous=NORMAL when WAL is active. Keep explicit journal mode and synchronous overrides available for WordPress plugin connections, including initial installation.
@JanJakes
Copy link
Copy Markdown
Member Author

CI timing notes from the first PR run:

Baseline caveat: WordPress PHPUnit Tests is configured for pull_request and push to main, while this repo's default branch is trunk, so I used the latest completed comparable PR run against the same base as the baseline: GitHub Actions workflow updates, run 25803560254.

  • WordPress PHPUnit Tests: 10m40 job time vs 11m06 baseline. Test step was 10m26 vs 10m56 baseline.
  • WordPress PHPUnit Tests / Rust extension: 8m58 job time vs 11m04 baseline. Test step was 5m12 vs 6m25 baseline.
  • End-to-end Tests: 5m06 vs 7m28 baseline.
  • WordPress End-to-end Tests: 5m26 vs 9m38 baseline.
  • The regular PHPUnit Tests matrix passed, but timings were mixed rather than a clear throughput win.

The E2E improvements look heavily affected by setup/cache variance, especially browser install time. The WordPress PHPUnit test-step deltas are the more relevant signal for the WAL change.

@JanJakes
Copy link
Copy Markdown
Member Author

CI timing comparison after repeated runs:

Methodology:

  • WAL branch: PR Default SQLite connections to WAL #405, three PR-check attempts.
  • Trunk baseline: temporary draft PR CI baseline for WAL comparison #406 from an empty commit on top of trunk, so the tree was identical to trunk. Three PR-check attempts.
  • Path-filtered CS and MySQL Parser Extension Tests could not be triggered by an empty diff, so those were run three times via workflow_dispatch on trunk and wal.
  • Excluded one cancelled baseline WordPress End-to-end Tests attempt that hit the 20-minute timeout; replaced it with a successful rerun. Also excluded one cancelled manual WAL parser-dispatch outlier where a single PHP 8.3 job got stuck; replaced it with a successful rerun.

Median timings:

Metric trunk WAL Delta
WordPress PHPUnit job 10:26 10:24 -0.3%
WordPress PHPUnit test step 10:12 10:10 -0.3%
WordPress PHPUnit Rust job 10:25 9:01 -13.4%
WordPress PHPUnit Rust test step 6:18 5:16 -16.4%
WordPress E2E job 5:28 5:42 +4.3%
WordPress E2E test step 4:19 4:30 +4.2%
Plugin E2E job 4:45 5:01 +5.6%
Plugin E2E test step 3:39 3:50 +5.0%
MySQL Proxy job 0:16 0:14 -12.5%

Low-level PHPUnit matrix medians were mixed:

Job trunk WAL Delta
PHP 7.2 / SQLite 3.27.0 3:12 4:06 +28.1%
PHP 7.3 / SQLite 3.31.1 2:27 3:03 +24.5%
PHP 7.4 / SQLite 3.34.1 2:37 2:48 +7.0%
PHP 8.0 / SQLite 3.37.0 2:40 2:41 +0.6%
PHP 8.1 / SQLite 3.40.1 2:44 3:03 +11.6%
PHP 8.2 / SQLite 3.45.1 3:03 2:58 -2.7%
PHP 8.3 / SQLite 3.46.1 2:49 2:57 +4.7%
PHP 8.4 / SQLite 3.51.2 2:59 2:55 -2.2%
PHP 8.5 / SQLite latest 2:42 2:58 +9.9%

Path-filtered manual-dispatch checks were mostly neutral/noisy. CS was identical at 0:16 median. Parser-extension medians were mixed per matrix job, generally within runner variance except PHP 7.3 and PHP 8.4, where WAL was slower in these dispatch samples.

Readout: the strongest positive signal is WordPress PHPUnit with the Rust parser extension. Regular WordPress PHPUnit is essentially flat. E2E and low-level PHPUnit do not show a consistent WAL win in these CI samples.

@JanJakes
Copy link
Copy Markdown
Member Author

Local concurrent traffic benchmark against latest trunk:

Methodology:

  • trunk: origin/trunk at 25510901.
  • wal: temporary worktree from origin/trunk plus 02a14006, so the comparison isolates the WAL change from branch staleness.
  • Local runtime: PHP 8.5.5, SQLite 3.53.0.
  • Driver-level benchmark, not full HTTP/PHP-FPM.
  • 16 concurrent PHP worker processes, each with its own SQLite driver connection to the same DB file.
  • 3 runs per profile, 300 operations per worker per run, fresh DB per sample.
  • Seeded WordPress-shaped tables: posts, postmeta, comments, commentmeta, terms, term taxonomy, relationships, and options.
  • Operations included page views, archive queries, searches, comment writes, transient option updates, and post updates.

Median results:

Profile Variant SQLite mode Ops/sec p50 p95 p99 Errors
public 90R/10W trunk DELETE / FULL 2149.0 2.71ms 25.32ms 67.64ms 0
public 90R/10W WAL WAL / NORMAL 6780.6 1.78ms 4.59ms 8.84ms 0
write burst 70R/30W trunk DELETE / FULL 1102.4 3.06ms 60.78ms 148.75ms 0
write burst 70R/30W WAL WAL / NORMAL 4523.7 1.57ms 4.48ms 32.89ms 0

Readout:

  • Public traffic: WAL was +215.5% ops/sec, p95 latency -81.9%, p99 latency -86.9%.
  • Write-burst traffic: WAL was +310.4% ops/sec, p95 latency -92.6%, p99 latency -77.9%.
  • No SQLITE_BUSY or other errors occurred in any sample.

This benchmark is intentionally narrower than a full WordPress HTTP stack, but it exercises the production MySQL-on-SQLite driver with concurrent PHP processes and a WordPress-shaped read/write workload. The result is a much clearer WAL benefit than the GitHub Actions wall-clock timings, especially in tail latency under concurrent reads and writes.

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