Selective RLS measurements (10M profile)
Tested source commit: 455351ca049a6dac73852fd90f0fd0a97d6556e4.
Installed library SHA-256:
d33cf6a74a76c3c8a9d7e46cff251cb9b501dde953d6d5523e9e62ab469c399d.
This was an optimized PostgreSQL 17.11 Linux aarch64 development build
(pg17 development, without pg_test). Build and runtime facts are separately
attested in runtime-attestation.json; the library hash does not identify its
features by itself.
All four cases completed ten measured samples after three warmups. Exact-result, percentile, strategy and resource validation passed within the frozen budgets. The source and library stayed unchanged and the owned cluster stopped cleanly. These measurements cover this profile, not every query shape or a latency SLA.
| Case | Selected strategy | p95 total (ms) | Maximum policy-source rows |
|---|---|---|---|
| Identity one-hop, automatic | Lazy | 2792.5595 | 3 |
| Same identity query, forced eager | Eager | 64947.0115 | 30000000 |
| Sparse-policy whole-source scan | Eager | 28408.12585 | 300000 |
| Identity one-hop, no RLS | Lazy | 321.46415 | 0 |
Automatic and forced eager identity queries produced the same one-row signature
in every sample. Automatic execution performed no repeated GQL read recheck;
forced eager and no-RLS execution rechecked one matched row, and the whole-source
case rechecked ten. samples.csv and summary.csv retain every measured timing,
signature, memory charge, work charge and recheck count.
The fixture contains ten million scalar nodes plus ten million composite nodes, with two N-1 relationship mappings: 20 million nodes and 19,999,998 relationships in total. The profile name is not the total graph node count. The CSR build took 374614.234252 ms and reported 1953.179370880127 MiB of projection memory.
The container had four CPUs and a 6 GiB memory limit inside a Docker Desktop VM
configured with 12 GiB. The cgroup lifetime memory.peak reached exactly 6 GiB
and memory.events.max increased from 0 to 31679, indicating pressure at the
container limit. No OOM or OOM-kill event occurred. This run does not demonstrate
spare container memory. A previous preparation attempt with the same container
limit on an approximately 8 GiB outer VM was killed by a global VM OOM during
build, before any query samples. It is retained as a separate preparation
failure, not a latency observation.
Query workspace was 2048 MiB, the graph memory limit was 4096 MiB, the work limit
was 100 million units, and query spill remained 4096 MiB. Only fixture building
used a 16384 MiB spill allowance, reset before query execution. The effective
settings are retained in work-governor.csv, build-spill-setting.csv and
query-spill-setting.csv. The frozen query acceptance budgets were unchanged.
Reproduction
Use the tested commit, the attested development-only release build and a fresh
disposable PostgreSQL 17 cluster with the recorded CPU/memory envelope. Configure
fsync=on, autovacuum=off, TCP listening off, and the effective graph governors
in runtime-attestation.json. Use an owned Unix socket and ordinary libpq
connection settings. The maintained runner does not explicitly ANALYZE the
fixture.
Copy graph/tests/heavy/rls_large_table_baseline.sh outside the clean checkout.
Set only the copy’s SCRIPT_DIR to the absolute source graph/tests/heavy
directory, so its source provenance still names the clean checkout. Around its
single SELECT * FROM graph.build(); preparation statement, add:
SET graph.spill_disk_limit_mb = 16384;
SELECT * FROM graph.build();
RESET graph.spill_disk_limit_mb;
Record current_setting('graph.spill_disk_limit_mb') immediately before and
after that build, as in the retained setting CSVs. No query SQL or query budget
changes are needed. The original runner, adapted runner and adaptation diff
hashes are recorded in validation.json; local copy/capture paths affect the
adapted hashes.
NODE_COUNT=10000000 COMPOSITE_COUNT=10000000 SAMPLES=10 WARMUPS=3 QUERY_MEMORY_MB=2048 PERSIST_ON_BUILD=on STATEMENT_TIMEOUT_MS=6000000 RUN_PROFILE=p5_release SKIP_INSTALL=1 PG_VERSION_FEATURE=pg17 DBNAME=pggraph_fresh_measurement ROLE_NAME=pggraph_fresh_reader OUTPUT_DIR=/path/to/fresh-output PG_CONFIG=/path/to/pg_config bash /path/to/copied-runner.sh
Percentiles use PostgreSQL percentile_cont interpolation. Visibility
source_rows counts returned policy rows, not all PostgreSQL rows examined or
hydration work. Zero GQL rechecks does not imply zero hydration SQL. Governor
memory is distinct from process RSS and cgroup lifetime memory. The 1M and 10M
profiles used different source commits and resource envelopes, so their timings
are not a controlled scaling comparison.
Measurement CSVs and plans are copied byte-for-byte. redactions.json records
only local host/path removal from run metadata and the validator’s source path.
selection-provenance.json identifies original file and validation hashes;
selection itself is not validation. Relative log references in attempts.csv
identify omitted original logs. Cluster files and local qualification wrappers
are also omitted. SHA256SUMS covers all selected files except itself.