You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PostgreSQL still serves usage analytics from live message and usage-event queries, while SQLite has a normalized facts path. The repository has no PostgreSQL-specific benchmark for the five public usage methods or their refresh cost, so the query-shape choice in issue #1451 lacks a reproducible baseline.
This adds an opt-in PostgreSQL 16 benchmark substrate covering varied read windows, all five usage methods, breakdowns, complete SQLite/PostgreSQL result checks before timing, an initial full push into an initialized empty schema, a fixed-cardinality one-message delta, catalog probes, eligible usage input counts, token-usage bytes, allocations, and the existing parity fixture. It records the constraints for a later optimization while leaving production queries, schemas, pricing, and public results unchanged. The benchmark remains outside the normal CI bench gate because it requires Docker.
Benchmark methodology has two medium-severity issues that can produce misleading results.
Medium
internal/postgres/usage_bench_pgtest_test.go:297 — DeltaPush permanently appends a message on every iteration. Since PostgreSQL synchronization replaces the session’s complete message set, each operation processes progressively more rows, and calibration runs inherit prior mutations. Consequently, ns/op and messages_pushed depend on b.N and calibration history instead of measuring a fixed delta workload. Reset to a fixed-size fixture for each operation, or mutate an existing message while keeping session cardinality constant.
internal/postgres/usage_bench_pgtest_test.go:74 — The fixture performs a full push before ColdPush, so the benchmark runs against an already-created, populated, warmed schema. It measures repeated full replacement rather than the documented cold-push path. Use an empty schema for each measured operation, or rename the benchmark to FullRepush and add a genuine initial-push benchmark.
Benchmarks are useful, but two medium-severity measurement and validation gaps could produce misleading results.
Medium
Makefile:366, internal/postgres/usage_bench_pgtest_test.go:228 — The benchmark target skips TestPGUsageBenchmarkFixture, while its validator checks only for non-empty results. Incorrect usage totals or breakdowns can therefore appear valid despite documentation claiming exact verification. Run the fixture test from this target, or compare every PostgreSQL result against the expected/local parity snapshot before resetting the timer.
internal/postgres/usage_bench_pgtest_test.go:255 — rows_scanned counts eligible fixture rows returned by two counting queries; it does not measure rows scanned by the five benchmarked methods, account for their differing query shapes, or expose sequential scans and filtered-out rows. Rename it to an eligible-input-row metric, or collect actual per-query scan statistics from PostgreSQL execution plans.
Tests add useful PostgreSQL parity coverage, but one medium-severity fixture gap could allow session-count regressions to escape detection.
Medium
internal/postgres/usage_facts_parity_pgtest_test.go:289 — Giving the activity-only message token usage makes it eligible for normal usage aggregation. No benchmark window now covers a tokenless assistant session that should appear only in GetUsageMatchingSessionCount, so an optimization that incorrectly requires token data could pass. Keep this message tokenless and ensure a tested window includes it; add a separate historical token-bearing fixture if needed to vary window workloads.
The PR is security-clean, but three medium-severity benchmark and parity coverage gaps should be addressed.
Medium
internal/postgres/usage_bench_pgtest_test.go:280 — The performance fixture contains only five eligible usage rows. The one- and seven-day cases are identical, while the thirty-day and all-history cases differ by only one row, so the benchmark primarily measures fixed query and round-trip overhead rather than aggregation scaling. Add a configurable, representative bulk fixture distributed across the date windows, retaining the small fixture for correctness checks.
internal/postgres/usage_bench_pgtest_test.go:432 — The delta benchmark checks attempted push counts and cardinality but does not verify that changed token data reaches PostgreSQL usage results. A stale aggregate could therefore benchmark well while passing. With timing stopped, compare affected PostgreSQL usage results against SQLite or assert the expected toggled token/cost values after each push; also validate usage output after cold pushes.
internal/postgres/usage_facts_parity_pgtest_test.go:244 — The documentation claims coverage of per-survivor microdollar rounding, but all configured rates produce exact whole microdollars per token. The parity preflight would miss an implementation that aggregates fractional costs before rounding. Add multiple surviving rows whose fractional-microdollar costs produce a different result when rounded individually versus after aggregation, and assert exact totals.
One medium-severity issue remains in the PostgreSQL benchmark fixture.
Medium
internal/postgres/usage_bench_pgtest_test.go:22 — The fixture has at most 29 eligible rows, including only 24 identical single-message sessions. This does not exercise scale-sensitive query plans, joins, deduplication, or breakdown cardinality, so it is insufficient evidence for the documented PostgreSQL-native architecture decision. Add a configurable, production-scale fixture with multiple messages per session and varied projects, agents, models, and dates, and report the configured scale with each benchmark.
Benchmarks need a more representative dataset before they can meaningfully evaluate the proposed optimization.
Medium
internal/postgres/usage_bench_pgtest_test.go:24 — The read benchmark has only 197 eligible rows; cold push uses five messages, and delta push mutates a one-message session. Fixed overhead and tiny-table PostgreSQL plans will dominate, masking scaling and write-amplification behavior. Use a representative large fixture comparable to the existing 100,000-row usage benchmark and analyze the loaded tables; keep the small fixture for exact correctness checks.
Benchmark changes look safe overall, but one reproducibility issue should be fixed.
Medium
internal/postgres/usage_bench_pgtest_test.go:380 — The read benchmark queries immediately after inserting 100,000 messages without running ANALYZE. A fresh schema lacks column statistics, and asynchronous auto-analysis may change query plans between repetitions, producing unrealistic or inconsistent results. Run ANALYZE after fixture.prime(b) and before preflight or timing.
I'm working on some more systematic benchmarking of the postgres support, so this will help, but I may make some PRs related to this in the near future
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PostgreSQL still serves usage analytics from live message and usage-event queries, while SQLite has a normalized facts path. The repository has no PostgreSQL-specific benchmark for the five public usage methods or their refresh cost, so the query-shape choice in issue #1451 lacks a reproducible baseline.
This adds an opt-in PostgreSQL 16 benchmark substrate covering varied read windows, all five usage methods, breakdowns, complete SQLite/PostgreSQL result checks before timing, an initial full push into an initialized empty schema, a fixed-cardinality one-message delta, catalog probes, eligible usage input counts, token-usage bytes, allocations, and the existing parity fixture. It records the constraints for a later optimization while leaving production queries, schemas, pricing, and public results unchanged. The benchmark remains outside the normal CI bench gate because it requires Docker.
Refs #1451