perf: optimize import persistence for 0.3.14
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-29 18:56:11 +02:00
parent 0d953173a8
commit cbd7220d8d
23 changed files with 1262 additions and 46 deletions
+14
View File
@@ -0,0 +1,14 @@
# Importperformancebaseline 0.3.13
Gemeten op 2026-07-29 in een disposable PostgreSQL-database op Unraid (Linux 6.12.54, Python 3.13.14, 20 CPU's). De vaste fixture bevat 250 geldige HTML-documenten met dezelfde externe vacature-identiteit: één create en 249 idempotente duplicate-updates. Concurrency is bewust 1; netwerk, Celery, Ollama en mail zijn uit de meting gehouden.
| Metriek | 0.3.13 |
|---|---:|
| Importduur | 16.358,158 ms |
| p50 per document | 63,034 ms |
| p95 per document | 79,871 ms |
| Throughput | 15,283 documenten/s |
| Importqueries | >9.000 (loggerlimiet bereikt) |
| Piekgeheugen | 26,582 MB |
Correctheidsankers: parserdekking 12/12, dedupeprecision 1,0, deduperecall 1,0 en rankingchurn 0. De overschrijding van 9.000 queries is als ondergrens gerapporteerd, niet als exact getal.
+14
View File
@@ -0,0 +1,14 @@
# Finale importperformancemeting 0.3.14
De officiële runner gebruikt een database met verplichte prefix `vacatureradar_bench_`, weigert SQLite, externe databasehosts en publieke productiedomeinen, migreert en flusht de disposable database, voert één warm-up uit en meet daarna drie iteraties van 250 documenten. Het machineleesbare bewijs staat in `artifacts/import-performance-report.json`.
| Metriek | 0.3.13 | 0.3.14 gemiddeld | Verbetering |
|---|---:|---:|---:|
| Importduur | 16.358,158 ms | 9.040,123 ms | 44,74% lager |
| p50 | 63,034 ms | 32,900 ms | 47,80% lager |
| p95 | 79,871 ms | 52,296 ms | 34,53% lager |
| Throughput | 15,283/s | 28,031/s | 83,42% hoger |
| Importqueries | >9.000 | 3.264 | minstens 63,73% lager |
| Piekgeheugen | 26,582 MB | 18,799 MB | 29,28% lager |
Alle drie iteraties zijn gelijk voor queryvolume en queryfamilies. De kwaliteitsankers bleven parser 12/12, precision 1,0, recall 1,0 en rankingchurn 0. De fixture resulteert per iteratie in één vacature, één versie, behouden veldprovenance, 250 historische ScoreRuns en 249 idempotente duplicates.
@@ -0,0 +1,10 @@
# Importperformancetraceability
| Acceptatie | Implementatie | Bewijs |
|---|---|---|
| Veilige isolatie | `scripts/benchmark_import.py`, `scripts/run_import_benchmark.sh` | negatieve identitytests en disposable PostgreSQL-run |
| Meetbare reductie | run-local caches, gebundelde provenance en score-snapshotcopy | baseline/finaal rapport en machine-JSON |
| Geen functionele regressie | bestaande dedupe/scoringregels ongewijzigd | pipeline-, dedupe- en benchmarktests |
| Historiek en provenance | scorecopy per import, evidence bulk sync | integratietest met 20 herhaalde documenten |
| Queryregressie voorkomen | execute-wrapper en budgettest | stabiel 3.264 queries per 250; minder dan 300 per 20 in test |
| Releasekwaliteit | VR-228, gates, acceptance en operationsdocs | `docs/ai/PROJECT_STATE.md` en `FINAL_ACCEPTANCE.md` |
+12
View File
@@ -0,0 +1,12 @@
# Importqueryanalyse 0.3.14
De hot path liep van `process_raw_document` via parsing en `persist_draft` naar employer-resolutie, deduplicatie, alias/provenance, versiebeheer en scoring. Profiling wees vier dominante oorzaken aan:
1. Dezelfde werkgever en actieve profielen werden voor elk document opnieuw opgehaald.
2. Veldprovenance gebruikte per veld een afzonderlijke `update_or_create`.
3. Een inhoudelijk ongewijzigde waarneming schreef opnieuw een versie en berekende alle scores volledig.
4. `last_changed` verschoof ten onrechte bij alleen een nieuwe `last_seen`-waarneming.
De oplossing blijft binnen de modulaire monoliet en transacties: een import-run krijgt een lokale `PersistenceContext`, provenance wordt per alias gelezen en gebundeld geschreven, versies ontstaan alleen bij inhoudelijke wijziging en een ongewijzigde job kopieert het laatste ongewijzigde scoresnapshot. Daardoor blijft iedere `ScoreRun` historisch aanwezig, terwijl deterministische scoring niet opnieuw wordt uitgevoerd. De cache leeft nooit buiten één seriële import-run en verandert workerisolatie of deduplicatieregels niet.
De database-executieteller rapporteert per 250 items exact: 1.256 SELECT, 1.003 INSERT, 499 UPDATE, 253 SAVEPOINT en 253 RELEASE; totaal 3.264 importexecuties. De drie officiële iteraties geven identieke queryfamilies.
+4
View File
@@ -1,5 +1,9 @@
# Performanceaudit 2026-07-29
## Importoptimalisatie 0.3.14
De eerder geregistreerde importhotspot is opgelost en reproduceerbaar gemeten in een disposable PostgreSQL-database. Tegenover de 0.3.13-baseline daalt de gemiddelde 250-itemimport van 16.358,158 naar 9.040,123 ms; p95 daalt van 79,871 naar 52,296 ms en queryvolume van meer dan 9.000 naar exact 3.264. Zie `IMPORT_PERFORMANCE_BASELINE.md`, `IMPORT_QUERY_ANALYSIS.md` en `IMPORT_PERFORMANCE_FINAL.md`.
## Baseline
- Lokale quickbenchmark: 250 invoeritems op Windows 11, Python 3.13, 16 CPU-threads.
+1
View File
@@ -16,3 +16,4 @@
| Back-up/restore | custom dump, media en runbook | geïsoleerde restore, exacte tellingen en aparte applicatiestart | implemented and live verified |
| Rollback | immutable vorige en huidige imagetags | oude image healthy, daarna 0.3.13 opnieuw healthy | implemented and live verified |
| Externe identity/mail | versleutelde configuratieboundary | `USER_INPUT_REQUIRED.md` | optional external action |
| Importperformance 0.3.14 | run-lokale caches, evidence bulk sync en scorecopy | geïsoleerde 3-run PostgreSQL-meting en regressietests | implemented and verified |