Skip to content

docs: bench methodology + tooling under benchmark/#66

Merged
NikolayS merged 6 commits intomainfrom
docs/bench-methodology
Apr 30, 2026
Merged

docs: bench methodology + tooling under benchmark/#66
NikolayS merged 6 commits intomainfrom
docs/bench-methodology

Conversation

@NikolayS
Copy link
Copy Markdown
Owner

@NikolayS NikolayS commented Apr 18, 2026

Summary

Adds a complete `benchmark/` directory documenting the methodology, tooling, and operational lessons from the pgque-vs-pgq-vs-pgmq-vs-river-vs-que-vs-pgboss-vs-pgmq-partitioned bench that backs #61 (the held-xmin bloat issue) and #62 (the subscription/tick rotation fix).

The content is strictly additive — no pgque production SQL is touched. Everything new sits under `benchmark/`.

Contents

  • `benchmark/README.md` — entry point + quick-start.
  • `benchmark/METHODOLOGY.md` — the bench methodology: workload shape, observability stack (pg_ash + pg-flight-recorder), phase scheduler, per-system patterns. Hardware: AWS i4i.2xlarge, PG18, 1.5 h with 30-min held-xmin window.
  • `benchmark/OPS_GOTCHAS.md` — 15 operational lessons from running this on AWS (NVMe auto-mount, pg_partman stale `part_config` rows, que `que_validate_tags` leftovers, pgboss covering index, pgq ticker daemon, pgque PG18 xid8 bug, spot reclaim mitigation, ASH prereqs, NOTICE-based instrumentation, etc.).
  • `benchmark/HARDWARE.md` — i4i.2xlarge specs, PG tuning, expected microbench baselines.
  • `benchmark/tooling/` — 7 samplers + daemons: `bloat_sampler.py`, `sys_metrics_sampler.py` (v2 with IOPS + latency), `pg_stat_statements_snapshot.py`, `parse_events_consumed.py`, `idle_in_tx.py` (the inducer), `pgq_ticker_daemon.py`, `microbench.sh`.
  • `benchmark/runners/` — `run_r7.sh` (phase-scheduled orchestrator), `clean_reinstall.sh`, `fix_nvme_mount.sh`.
  • `benchmark/consumers/` + `benchmark/producers/` — the 7 instrumented SQL claim patterns (DO + `RAISE NOTICE 'ev ts=% n=%'`), one per queue system.
  • `benchmark/install/` — per-system installers + shared `bootstrap.sh` (PGDG PG18 + pg_cron + pg_stat_statements + pg_ash + pgfr) + `install/README.md`.
  • `benchmark/charts/` — `r5_analyze.py`, `r6_smoke_chart.py` (linear-scale only, per project rule).
  • `benchmark/gifs/` — `r4_gif_v17_solarized.py` (dead-tuples animated), `r4_gif_tps_solarized.py` (TPS/latency animated).

Why now

PR #62 is the rotation fix for the held-xmin bloat pattern from #61. This PR is the evidence PR: the harness that proves #62 works, the ops playbook so a reviewer can reproduce, and the catalog of operational surprises we hit so the next person doesn't rediscover them.

Sanitation

  • All [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} matches in committed files are 127.0.0.1 (DB connections on the VM itself) — no AWS IPs, no public IPs.
  • Docs use <pgque-ip>, <your-ssh-key> placeholders.
  • No tokens, no AWS creds, no SSH private keys, no DB passwords.
  • Scripts that run on the VMs keep their 127.0.0.1 connection strings since that's operationally correct for local psql / pgbench.

Test plan

  • Review METHODOLOGY.md cross-references (all in-doc links resolve to files that exist under benchmark/).
  • Review OPS_GOTCHAS.md for completeness — any ops lesson missing?
  • Spot-check install/bootstrap.sh for any leaked IPs or tokens before merge.
  • Sanity-run runners/run_r7.sh pgque on a fresh i4i.2xlarge once PR Rotate subscription and tick tables to avoid held-xmin bloat (#61) #62 lands.

Refs: #61, #62.

Copy link
Copy Markdown
Owner Author

@NikolayS NikolayS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #66 Security Audit — NikolayS/pgque docs/bench-methodology

Audited commit: c8618af (tip of origin/docs/bench-methodology)
Scope: 39 files / 3,366 LOC under benchmark/
Auditor: automated scan (read-only, no modifications)

Summary

PASS — no secrets found. Ready to mark ready-for-review.

Hard secrets scan

Pattern Findings
AWS access keys (AKIA…) 0
AWS secret key references (aws_secret_access_key / aws_access_key_id) 0
GitHub tokens (ghp_, gho_, ghs_, github_pat_) 0
GitLab tokens (glpat-…) 0
Slack tokens (xoxb-…) 0
Private key headers (BEGIN OPENSSH/RSA/EC/PRIVATE/DSA) 0
PG credential files (pg_service.conf, .pgpass) 0
Quoted password = '...' 0
Postgres URIs with embedded password (postgres://user:pw@…) 0
Bearer … tokens 0
Raw 64-hex tokens 0

Soft leakage

Pattern Findings Notes
Public IPv4 addresses 0 Only 127.0.0.1 appears; no RFC1918-external, no public IPs
arn:aws:… 0
12-digit AWS account IDs 0
~/.ssh/… or *.pem paths 0
EC2 public hostnames (ec2-…compute.amazonaws.com) 0
EC2 instance IDs (i-…) 0
PGPASSWORD, export *_TOKEN=…, curl Authorization headers 0
Inline ssh user@host / scp … commands 0
Base64-looking long strings 1 (false positive — Go import path com/riverqueue/river/riverdriver/riverpgxv5 in install/install_river.sh:34)

IPv4 references (all loopback, expected)

All 12 IPv4 hits in the tree are 127.0.0.1 in passwordless local DSNs, consistent with the pg_hba trust-for-localhost bootstrap in install/bootstrap.sh:77. These are expected for single-VM benchmarks:

  • tooling/idle_in_tx.py:8, tooling/bloat_sampler.py:10, tooling/pg_stat_statements_snapshot.py:16, tooling/pgq_ticker_daemon.py:9
  • install/install_river.sh:13,53, install/install_pgboss.sh:13,61
  • install/bootstrap.sh:77
  • runners/run_r7.sh:55,62,69

Historical commits

  • Commits touching benchmark/ on this branch: 1 (c8618af)
  • Removed-but-still-in-history secrets: none
  • Full git log -p -- 'benchmark/**' scanned for AKIA|ghp_|gho_|ghs_|glpat|xoxb|BEGIN (OPENSSH|RSA|EC|PRIVATE|DSA)|aws_secret|bearer — zero matches

No squash / force-push required.

File-type specific checks

  • Shell scripts (install/*.sh, runners/*.sh, tooling/*.sh): no hardcoded credential env vars
  • Python (tooling/*.py, charts/*.py, gifs/*.py): all DSNs are passwordless localhost; no dsn=…password=… or psycopg2.connect(…, password=…)
  • Markdown (README.md, METHODOLOGY.md, HARDWARE.md, OPS_GOTCHAS.md, install/README.md): zero hits on AWS_, aws_access_key_id, EC2_, S3_BUCKET
  • SQL (consumers/*.sql, producers/*.sql, install/pgmq-partitioned_setup_5min.sql): no credentials

Recommendation

PASS — the branch is safe to mark ready-for-review. No redaction, no force-push needed.

Non-blocking observations (not required for merge):

  1. DSNs throughout tooling/*.py and install/*.sh assume user=postgres with trust auth on 127.0.0.1. This is correct for the documented benchmark VM setup but worth a one-line note in benchmark/README.md so that copy-pasters don't run these against a prod-like host. Already partially covered by OPS_GOTCHAS.md — minor.
  2. None of the scripts take credentials from env vars (no PGPASSWORD fallbacks). If the methodology is ever extended to RDS/remote PG, reviewers will want os.environ.get("PGPASSWORD") hooks rather than hardcoded DSN strings. Not a security issue today.

Scan methodology: hard-pattern regex (AWS/GitHub/GitLab/Slack tokens, private-key headers, quoted passwords, DSN-embedded credentials, Bearer tokens, 64-hex), soft-pattern regex (public IPv4, ARN, 12-digit account IDs, SSH/PEM paths, EC2 hostnames & instance IDs, base64-looking blobs), env-var extraction, and full branch git log -p sweep.

NikolayS pushed a commit that referenced this pull request Apr 19, 2026
Three standalone Python scripts that consume per-system bench output at
/tmp/bench_r8_full/<sys>/ and produce the Solarized-Dark chart set used
in the R8 review post (issue #77).

- r8_analyze.py: 6-panel overlay across 7 systems (throughput, bloat, CPU,
  NVMe write, true backlog, delivery-lag p99). LINEAR y-axes everywhere;
  p99 lag clipped at 5s (no log scale). Backlog column is
  producer_total - consumer_total, not n_live_tup snapshot.
- r8_ash_analyze.py: per-system stacked-area of ASH wait-event categories
  (CPU* / IO / LWLock / Lock / Client / IPC / Activity / Other) over 2h,
  1-minute buckets, LINEAR 0-1.0 proportion.
- r8_pgfr_analyze.py: 4-column-x-7-row pgfr deep-dive. Col 1 top-5 queries
  by cumulative total_exec_time with actual truncated query text (DO
  blocks unwrapped to first PERFORM/SELECT/UPDATE/DELETE/INSERT
  statement — no more opaque q1/q2/q3 labels). Col 2 per-query buffer hit
  rate. Col 3 per-query wal_bytes. Col 4 global WAL rate MiB/s + active
  backends twin-axis. Falls back to pgss.csv for systems without pgfr
  installed.

Styling (Solarized Dark rcParams block, phase bands, legend placement)
inherits from benchmark/charts/r6_smoke_chart.py in PR #66.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NikolayS NikolayS force-pushed the docs/bench-methodology branch from c8618af to 03bc107 Compare April 30, 2026 09:26
@NikolayS NikolayS marked this pull request as ready for review April 30, 2026 09:26
@NikolayS
Copy link
Copy Markdown
Owner Author

REV Review — PR #66 (post-scrub)

CI: 7/8 pass (test 14/15/16/17/18, client-smoke, verify); claude-review pending
Anti-leak scan (independent verification): HITS — 2 file references to private GitLab WI #77 + 1 commit-message leak (note ID + "issue #77" in subject)
Verdict: FIXES NEEDED

Blocking

  • [HIGH] anti-leak — benchmark/install/bootstrap.sh:41 and :44 still reference issue #77:

    # ── postgresql.conf tuning (same as issue #77) ───
    # ── pgq bench tuning (issue #77) ─────────────────
    

    GitHub issue small formatting tweak in reference.md #77 in this repo is unrelated (a reference.md formatting tweak by The-Alchemist). These two comments are residue from the private WI small formatting tweak in reference.md #77 in postgres-ai/postgresql-consulting/tests-and-benchmarks and per project rule (MEMORY.md: "WI refactor: rename to XXX; clarify log vs task queue #76/small formatting tweak in reference.md #77 PRIVATE — never link from public") must not appear in the public repo. The scrub commit 03bc107 claimed it cleaned R4/R5/R6/R8 round refs but missed these two bootstrap.sh comments. Suggested fix: drop the (... issue #77) parenthetical entirely — leave just # postgresql.conf tuning / # pgq bench tuning.

  • [HIGH] anti-leak — commit be9c9d0 subject + body:

    • Subject: docs: complete bench methodology + tooling + ops gotchas under benchmark/ (issue #77) — leaks WI small formatting tweak in reference.md #77 in the commit subject (permanent in git history once merged).
    • Body: METHODOLOGY.md: adapted from GitLab #77 note 3263767264 — leaks both GitLab #77 and the internal note ID.

    The scrub commit 03bc107 only edited file contents and the PR description; it did not amend the prior commit. Recommended action before merge: rebase + reword commit subjects/bodies of be9c9d0 and 03bc107 to drop GitLab/WI small formatting tweak in reference.md #77 references (the scrub commit's own message also enumerates GitLab URLs, note IDs, R4/R5/R6/R8, etc., which is itself documenting the leak vector). Even if reworded, squash-merging would also flatten this — but a rebase is cleaner.

Non-blocking

  • [MED] guidelines — shell style violations. CLAUDE.md requires set -Eeuo pipefail; the e94ece7 polish only fixed 3 of 9 shell scripts. Still non-conformant:

    • benchmark/install/bootstrap.sh:2set -euo pipefail
    • benchmark/install/install_pgmq.sh:2set -euo pipefail
    • benchmark/install/install_pgq.sh:2set -euo pipefail
    • benchmark/install/install_river.sh:2set -euo pipefail
    • benchmark/install/install_pgboss.sh:3set -euo pipefail
    • benchmark/runners/clean_reinstall.sh:3set -uo pipefail (missing -Ee)
    • benchmark/tooling/microbench.sh:3set -uo pipefail (missing -Ee)
  • [MED] bug — broken in-doc link. benchmark/OPS_GOTCHAS.md:185 references [install/install_pgque.sh](install/install_pgque.sh) which does not exist in the repo. Per benchmark/install/README.md:9, pgque install is driven from AMI userdata, so this script was never created. Suggested fix: rephrase to point at the steps quoted in install/README.md, or change to "re-clone the PR Rotate subscription and tick tables to avoid held-xmin bloat (#61) #62 branch and make install per install/README.md."

  • [LOW] guidelines — non-binary unit in shell comment. benchmark/install/install_pgboss.sh:27.9 GB disk sort pathology should be 7.9 GiB per CLAUDE.md (binary units in prose; PG config is the only exception, and this is a comment, not config).

  • [LOW] reproducibility — hardcoded external paths. benchmark/runners/run_r7.sh resolves auxiliary tools from $R7_DIR=/tmp/r7 and $R6_DIR=/tmp/r6 (lines 11–12, 48, 52, 107). Those scripts (sys_metrics_sampler.py, pg_stat_statements_snapshot.py, parse_events_consumed.py) actually live in benchmark/tooling/ in the repo. A fresh clone needs the user to copy/symlink them into /tmp/r6 and /tmp/r7 before run_r7.sh will succeed. Add a note in benchmark/README.md's quick-start, or change the script to fall back on tooling/.

Potential

  • [INFO] install_pgboss.sh:6 uses curl … | sudo bash (nodesource installer). This is the standard nodesource pattern and not actionable, just flagging that the PR template's security checklist asked specifically about curl … | sh. No fix needed.
  • [INFO] clean_reinstall.sh:32, :38 interpolate $j (a jobname selected from cron.job) directly into a SQL string without quoting. Inside this private bench harness with a controlled DB it's fine, but if anyone copy-pastes the snippet for production cleanup they should escape the value. Out-of-scope for this PR.

Summary

Area Findings Potential Filtered
Anti-leak 2 BLOCKING 0 0
Security 0 1 0
Bugs 1 1 0
Tests 0 0 0
Guidelines 2 0 0
Docs 0 0 0

REV-style review (security, bugs, tests, guidelines, docs). SOC2 items skipped per project policy. Anti-leak independently re-verified.

Nik Samokhvalov and others added 4 commits April 30, 2026 02:36
…ark/

Adds a strictly-additive benchmark/ directory documenting the
methodology, tooling, and operational lessons from the
pgque-vs-pgq-vs-pgmq-vs-river-vs-que-vs-pgboss-vs-pgmq-partitioned bench
that backs #61 and PR #62.

- README.md: entry point + quick-start
- METHODOLOGY.md: methodology fix per review feedback
- OPS_GOTCHAS.md: 15 operational lessons (NEW — NVMe mount, partman stale
  rows, que func leftovers, pgboss covering index, pgq ticker, pgque xid8
  bug, spot reclaim, ASH prereqs, NOTICE instrumentation, etc.)
- HARDWARE.md: i4i.2xlarge specs, PG tuning, microbench baselines
- tooling/, runners/, consumers/, producers/, install/, charts/, gifs/

No pgque production SQL is touched.
Refs: #61, #62.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- benchmark/runners/fix_nvme_mount.sh: switch to /usr/bin/env bash shebang;
  use set -Eeuo pipefail (was set -euo pipefail without -E)
- benchmark/runners/run_r7.sh: add -Ee flags to existing pipefail
- benchmark/runners/clean_reinstall.sh: read -r in two while-loops

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove all references to private internal URLs, round numbering
(R4/R5/R6/R8), and private repository paths from benchmark/ files.

- METHODOLOGY.md: drop internal URL + note IDs from header; remove
  internal posting-style section (§9); neutralize round refs; fix
  /tmp/bench_r<N> path reference
- README.md: drop internal reference comment
- HARDWARE.md: fix binary units (GB→GiB, TB→TiB); drop R7 round ref
- OPS_GOTCHAS.md: neutralize R4/R6 round refs in lessons; fix
  binary units (GB→GiB, MB/s→MiB/s)
- consumers/*.sql: drop "R6 instrumented" prefix from all 7 files
- runners/run_r7.sh: remove R6/R7 round refs from inline comments
- tooling/sys_metrics_sampler.py: remove R7 from docstring
- tooling/parse_events_consumed.py: remove R6 from docstring + msg
- charts/r5_analyze.py, r6_smoke_chart.py: remove Rn from docstrings,
  chart titles, and file-size output (KB→KiB)

PR description updated separately via gh pr edit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove private WI refs from bootstrap.sh:41,44 (replace with
  "see methodology notes")
- Fix set -Eeuo pipefail in 7 shell scripts that only had partial flags
- Fix broken OPS_GOTCHAS.md:185 link (install_pgque.sh → install/README.md)
- Fix binary unit in install_pgboss.sh:2 (GB → GiB)
- Fix run_r7.sh tool paths: resolve from benchmark/tooling/ by default
  instead of hardcoded /tmp/r7 and /tmp/r6; override via R7_DIR/R6_DIR

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NikolayS NikolayS force-pushed the docs/bench-methodology branch from 03bc107 to d586e35 Compare April 30, 2026 09:37
@NikolayS
Copy link
Copy Markdown
Owner Author

REV Review — PR #66 (round 2, post-loop)

CI: 7/8 SUCCESS (test 14/15/16/17/18, client-smoke, verify); claude-review IN_PROGRESS at scan time.
R1 BLOCKING resolution status:

  • [HIGH] anti-leak — bootstrap.sh:41,44 (issue #77) residue → addressed (commit d586e35 replaces with neutral wording; current file has no issue #77 hits)
  • [HIGH] anti-leak — ee105e8 subject (issue #77) + body GitLab #77 note 3263767264 + sibling commit 916a4f4 body GitLab mentions → addressed (history rewritten: be9c9d0ee105e8c, 042833c916a4f4; no gitlab / note <id> / issue #77 in git log origin/main..origin/docs/bench-methodology)

Independent anti-leak re-scan: CLEAN

Pattern set (excluding the documented vendored-data exception): issue #?7[67], gitlab\.com, note ?#?[0-9]{8,}, sahmed, artifact[_-]?registry, @AR\b, wi[ -]?#?7[67], hetzner.

Surface Hits
Commit history (git log origin/main..origin/docs/bench-methodology --format='%H %s%n%b') 0
PR diff (gh pr diff 66) 0
Working tree (benchmark/, docs/, README.md) 0
PR body 0
PR comments (excluding R1 review which itself quotes the prior leaks for record) 0

R[4-9]\b matches in the working tree (9 lines) are all legitimate filenames / vendored data per the documented exception: runners/run_r7.sh, charts/r5_analyze.py, /tmp/bench_r5 path. Flagging for awareness only — not blocking.

Blocking

None.

Non-blocking

  1. [LOW] consistency — runner/file naming runners/run_r7.sh, charts/r5_analyze.py, charts/r6_smoke_chart.py, gifs/r4_*.py keep round-numbered filenames. These are now de-coupled from the round refs that were scrubbed from contents (good — anti-leak passed). Optional follow-up: rename to neutral names (run_bench.sh, bloat_analyze.py) so the intent ("these are the bench tools, not a snapshot of round N") is obvious. Non-blocking; current state is internally consistent.
  2. [LOW] verify CI for claude-review claude-review was IN_PROGRESS during this scan; user should confirm it lands SUCCESS before merge.

Potential issues

None new in r2.

Summary table

Severity Count
BLOCKING 0
Non-blocking 2
Potential 0

Anti-leak independent verification

  • git log body+subject scan: clean
  • gh pr diff 66 scan: clean
  • working-tree scan (benchmark/, docs/, README.md): clean
  • PR body + comments scan: clean (R1's quoted strings are in R1's review, expected)
  • Shell-style: all 7 scripts now have set -Eeuo pipefail; grep -rL "set -Eeuo pipefail" benchmark/ --include="*.sh" returns empty.
  • Broken-link fix: grep -rn "install_pgque.sh" benchmark/ returns empty; OPS_GOTCHAS.md:185 now points to install/README.md and benchmark/install/README.md exists.

Verdict

READY FOR USER REVIEW

Both R1 BLOCKING anti-leak findings are resolved at history + working-tree + PR-metadata level. The two BLOCKING items from R1 are gone, the four non-blocking items are addressed (shell-style, broken link, binary units, R-round scrub), and r2's independent re-scan is clean. Pending CI: claude-review should be allowed to complete green before merge.


REV-style review (security, bugs, tests, guidelines, docs). SOC2 items skipped per project policy. Anti-leak independently re-verified on commit history, diff, working tree, PR body, and PR comments.

NikolayS and others added 2 commits April 30, 2026 03:15
- logging_collector=off does not mean zero log I/O; journald still
  writes to disk (#123)
- premake=20 planner cost is first-query-in-session, not per-query;
  root cause of steady-state regression is a follow-up (#124)
- add RAISE NOTICE observer-effect caveat for high-frequency use (#127)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NikolayS NikolayS merged commit 388853e into main Apr 30, 2026
8 checks passed
@NikolayS NikolayS deleted the docs/bench-methodology branch April 30, 2026 10:21
NikolayS pushed a commit that referenced this pull request Apr 30, 2026
Three standalone Python scripts that consume per-system bench output at
/tmp/bench_r8_full/<sys>/ and produce the Solarized-Dark chart set used
in the R8 review post (issue #77).

- r8_analyze.py: 6-panel overlay across 7 systems (throughput, bloat, CPU,
  NVMe write, true backlog, delivery-lag p99). LINEAR y-axes everywhere;
  p99 lag clipped at 5s (no log scale). Backlog column is
  producer_total - consumer_total, not n_live_tup snapshot.
- r8_ash_analyze.py: per-system stacked-area of ASH wait-event categories
  (CPU* / IO / LWLock / Lock / Client / IPC / Activity / Other) over 2h,
  1-minute buckets, LINEAR 0-1.0 proportion.
- r8_pgfr_analyze.py: 4-column-x-7-row pgfr deep-dive. Col 1 top-5 queries
  by cumulative total_exec_time with actual truncated query text (DO
  blocks unwrapped to first PERFORM/SELECT/UPDATE/DELETE/INSERT
  statement — no more opaque q1/q2/q3 labels). Col 2 per-query buffer hit
  rate. Col 3 per-query wal_bytes. Col 4 global WAL rate MiB/s + active
  backends twin-axis. Falls back to pgss.csv for systems without pgfr
  installed.

Styling (Solarized Dark rcParams block, phase bands, legend placement)
inherits from benchmark/charts/r6_smoke_chart.py in PR #66.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NikolayS added a commit that referenced this pull request Apr 30, 2026
* charts: add R8 analyzers (main + ASH + pgfr) to benchmark/charts/

Three standalone Python scripts that consume per-system bench output at
/tmp/bench_r8_full/<sys>/ and produce the Solarized-Dark chart set used
in the R8 review post (issue #77).

- r8_analyze.py: 6-panel overlay across 7 systems (throughput, bloat, CPU,
  NVMe write, true backlog, delivery-lag p99). LINEAR y-axes everywhere;
  p99 lag clipped at 5s (no log scale). Backlog column is
  producer_total - consumer_total, not n_live_tup snapshot.
- r8_ash_analyze.py: per-system stacked-area of ASH wait-event categories
  (CPU* / IO / LWLock / Lock / Client / IPC / Activity / Other) over 2h,
  1-minute buckets, LINEAR 0-1.0 proportion.
- r8_pgfr_analyze.py: 4-column-x-7-row pgfr deep-dive. Col 1 top-5 queries
  by cumulative total_exec_time with actual truncated query text (DO
  blocks unwrapped to first PERFORM/SELECT/UPDATE/DELETE/INSERT
  statement — no more opaque q1/q2/q3 labels). Col 2 per-query buffer hit
  rate. Col 3 per-query wal_bytes. Col 4 global WAL rate MiB/s + active
  backends twin-axis. Falls back to pgss.csv for systems without pgfr
  installed.

Styling (Solarized Dark rcParams block, phase bands, legend placement)
inherits from benchmark/charts/r6_smoke_chart.py in PR #66.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* charts: ASH y-axis shows active-session COUNT (standard ASH convention)

Previous proportion-based (0..1.0) rendering obscured the actual workload
difference. User feedback: standard ASH views plot the count of active
sessions, with each wait-event category as a stack layer whose height =
number of backends sampled in that category for the bucket.

Change bucket_stack() to return mean count per bucket (rows per bucket
divided by distinct-sample-timestamps), and set y-limit per subplot to
max(total) + 1 with integer ticks. Linear scale; no normalization.

Effect: pgque/pgq visibly jump from ~1 to ~2 active backends during the
TX phase (the held-xmin session joins, sitting on ClientRead); DELETE-
based systems sit at ~4-5 (their -c 4 consumers plus the producer) and
climb to ~6 during TX.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(charts): scrub round labels from captions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(charts): use binary units + update README index

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Nik Samokhvalov <nik@Niks-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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