Skip to content

Commit d39329c

Browse files
Merge pull request #375 from MPCoreDeveloper/perf/docs-session-summary
docs: session performance summary (tombstones + whole-file DML + marker range-read)
2 parents 0a9b9fc + d8b3976 commit d39329c

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

‎docs/CHANGELOG.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5555
DELETE (10K of 100K rows): ~0.54s/18.6K ops/s (flush rewrite)  **~0.16s/~64K ops/s (legacy)** and
5656
**~0.13s/~78K ops/s (fixed-width)**; comparative-harness DELETE (docs table): SQL ~0.82s/~12K 
5757
**~0.24s/~41K ops/s**, Direct ~0.63s/~16K  **~0.17s/~58K ops/s**  DELETE is back on par with UPDATE.
58+
- **Whole-file DML resolution + marker range-read (2026-09-03)** ÔÇö batch DELETE/UPDATE on the
59+
comparative docs table no longer pays one pread pair per touched row: the small (Ôëñ32 MB,
60+
plaintext, legacy variable-length) `.dat` is read once and every target record is resolved from
61+
that snapshot (B1 key-only decode for DELETE, raw slice for the UPDATE fastPatch). Positions with
62+
an in-batch buffered overwrite are detected via `IStorage.HasBufferedOverwriteAt` and always fall
63+
back to the per-record read, so transaction write-behind semantics stay intact. DELETE tombstone
64+
markers resolve their record lengths from a single whole-file read instead of one pread per marker.
65+
The canonical-DELETE scanner (which never consumed `WHERE`, so the structured batch path was dead
66+
code in the harness) is fixed and covered by `CanonicalBatchDelete_EngagesStructuredPath`.
67+
Measured (same machine, Release, median of 3): comparative DELETE SQL ~12K  **~59K ops/s** and
68+
Direct ~16K  **~86K ops/s**; UPDATE SQL ~35K  **~44K ops/s**, Direct ~49K  **~63K ops/s**;
69+
`--pk` DELETE legacy ~64K  **~68K ops/s**, fixed-width ~78K  **~93K ops/s**. Session plan +
70+
attribution in `docs/performance/EXECUTION_PLAN_UPDATE_DELETE.md`.
5871
- **Dedicated SQL batch-INSERT fast path (WP14)** ÔÇö `ExecuteBatchSQL` INSERTs no longer build a
5972
per-row `Dictionary<string, object>`; VALUES clauses are parsed directly into column-ordered
6073
`object[]` rows (`PreparedInsertStatement.ParseValuesToArray`) and inserted via the new

‎docs/performance/EXECUTION_PLAN_UPDATE_DELETE.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,25 @@ DELETE 10K op de docs-tabel (comparative, Release) — attributie in de structur
7070

7171
**Ontdekte bug (gefixed):** `TryScanCanonicalDml`'s DELETE-tak consumente nooit de whitespace/het `WHERE`-keyword na de tabelnaam → elke canonieke `DELETE ... WHERE col = literal` viel terug op de regex-path → `DeleteMultipleKeys` + B1/W1 (PR #369/#370) waren **dead code in de benchmark-harness**. Fix + diagnostische teller `Database.CanonicalDeleteStatementsParsed` + regressietest `CanonicalBatchDelete_EngagesStructuredPath` (deze PR).
7272

73+
74+
## 8. Eindstatus 2026-09-03 (alles gemerged op master `0a9b9fc1`)
75+
Gemeten op master (Release, zelfde machine; median van 3 runs voor de comparative, 2 voor `--pk`):
76+
77+
| Operatie | SCDB SQL | SCDB Direct | SQLite | opmerking |
78+
|---|---:|---:|---:|---|
79+
| INSERT 100K | ~98-102K | ~103K | ~126-138K | al competitief |
80+
| UPDATE 10K | ~44K | ~63K | ~228K | voor sessie: SQL ~35K / Direct ~49K |
81+
| DELETE 10K | ~59K | ~86K | ~294K | **voor sessie: SQL ~12K / Direct ~16K** |
82+
| `--pk` DELETE legacy / FW | 68K / 93K | — | ~320K | FW was ~78K |
83+
84+
**Merged deze sessie (chronologisch):** #367 tombstones · #368 commit-time tombstones · #369 C4+B3 · #370 B1 · #371 canonieke DELETE-scanner-fix + W1 · #372 whole-file DELETE-resolutie · #373 marker range-read · #374 whole-file UPDATE-resolutie.
85+
86+
### Bewuste vervolgstappen (niet in deze sessie, zie secties 3-4)
87+
1. **Batch-PK stale/lazy-rebuild** na grote delete-batches — grootste open post; vereist eerst PK-index-refresh-infra (`Table.Index` is een plain property zonder lazy rebuild). Ontwerp nodig; daarna kan de per-rij read in DELETE vervallen.
88+
2. **Commit-marker schrijfbatching** (writes blijven per-offset; range-read zit er al in via #373).
89+
3. **Fase B (structureel):** fixed-width in-place engine + PageBased als OLTP-default — de weg naar ~1,2-1,5× van SQLite op UPDATE/DELETE.
90+
4. **Fase C/D (platform):** AOT/R2R als aparte meet-as, median-of-N in de harness, `dotnet-trace` per Fase-B-stap.
91+
7392
**Gevolg voor de attributie:** de per-rij read blijft nodig zolang de delete-core de auto-`rowid`-PK-waarde per rij moet wissen (gate-onderzoek: docs heeft PK-achtige index >1 geregistreerd). Grootste resterende hefbomen, nu met cijfers onderbouwd:
7493
1. **PK-onderhoud vervangen door één stale/lazy-rebuild** na een grote delete-batch (i.p.v. per-rij `Index.Delete`) → verwijdert ~30-50% van `core` én maakt de per-rij read overbodig (grootste winst op deze workload).
7594
2. **Marker-batching over een range-read** (commit-tombstones ~50 ms → enkele ms) als vervolg op C4.

0 commit comments

Comments
 (0)