release: implement site registry v0.5
All checks were successful
Standalone registry checks / check (push) Successful in 5m58s

This commit is contained in:
Nic Weyand 2026-09-13 14:42:39 -04:00
commit 557ba7cd69
Signed by: nicweyand
SSH key fingerprint: SHA256:2te+ycJIQON/Wo/dH6+ZkFSQ4HnHWpetV2azx9E65dQ
40 changed files with 3331 additions and 158 deletions

278
scripts/benchmark.py Normal file
View file

@ -0,0 +1,278 @@
#!/usr/bin/env python3
"""Run one registry operation and write a bounded, source-pinned benchmark report."""
import argparse
import hashlib
import json
import os
import platform
import resource
import selectors
import signal
import sqlite3
import subprocess
import sys
import time
from datetime import datetime, timezone
from pathlib import Path
MAX_MANIFEST_BYTES = 1024 * 1024
MAX_OUTPUT_BYTES = 16 * 1024 * 1024
def digest(data):
return hashlib.sha256(data).hexdigest()
def file_digest(path):
value = hashlib.sha256()
with path.open("rb") as stream:
while chunk := stream.read(1024 * 1024):
value.update(chunk)
return value.hexdigest()
def unique_object(pairs):
value = {}
for key, item in pairs:
if key in value:
raise ValueError("duplicate JSON key")
value[key] = item
return value
def read_manifest(path):
if path.is_symlink() or not path.is_file():
raise ValueError("source manifest must be a regular file")
data = path.read_bytes()
if len(data) > MAX_MANIFEST_BYTES:
raise ValueError("source manifest exceeds 1 MiB")
manifest = json.loads(data, object_pairs_hook=unique_object)
required = ("schema", "source", "snapshot", "sha256", "bytes")
if not isinstance(manifest, dict) or any(key not in manifest for key in required):
raise ValueError("source manifest is incomplete")
if (not isinstance(manifest["sha256"], str)
or len(manifest["sha256"]) != 64
or any(char not in "0123456789abcdef" for char in manifest["sha256"])):
raise ValueError("source manifest has invalid SHA-256")
if not isinstance(manifest["bytes"], int) or manifest["bytes"] <= 0:
raise ValueError("source manifest has invalid byte count")
return {
"manifest_sha256": digest(data),
"schema": manifest["schema"],
"source": manifest["source"],
"snapshot": manifest["snapshot"],
"source_object_sha256": manifest["sha256"],
"compressed_bytes": manifest["bytes"],
}
def database_counts(path):
if path is None or not path.exists():
return {"bytes": 0, "records": 0, "facts": 0}
if path.is_symlink() or not path.is_file():
raise ValueError("database must be a regular file")
connection = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
try:
page_count = connection.execute("PRAGMA page_count").fetchone()[0]
page_size = connection.execute("PRAGMA page_size").fetchone()[0]
tables = {
row[0]
for row in connection.execute(
"SELECT name FROM sqlite_schema WHERE type='table'"
)
}
records = connection.execute("SELECT count(*) FROM records").fetchone()[0] \
if "records" in tables else 0
facts = connection.execute("SELECT count(*) FROM facts").fetchone()[0] \
if "facts" in tables else 0
return {
"bytes": page_count * page_size,
"records": records,
"facts": facts,
}
finally:
connection.close()
def bounded_file(path):
if path.stat().st_size > MAX_OUTPUT_BYTES:
return None
return path.read_bytes()
def hardware():
cpu = "unknown"
cpuinfo = Path("/proc/cpuinfo")
if cpuinfo.is_file():
for line in cpuinfo.read_text(errors="replace").splitlines():
if line.startswith("model name"):
cpu = line.partition(":")[2].strip()
break
memory_kib = None
meminfo = Path("/proc/meminfo")
if meminfo.is_file():
first = meminfo.read_text(errors="replace").splitlines()[0].split()
if len(first) >= 2 and first[0] == "MemTotal:":
memory_kib = int(first[1])
return {
"operating_system": platform.system(),
"kernel": platform.release(),
"architecture": platform.machine(),
"cpu": cpu,
"logical_cpus": os.cpu_count(),
"memory_kib": memory_kib,
}
def run_bounded(command, stdout_path, stderr_path):
process = subprocess.Popen(
command,
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True,
)
streams = selectors.DefaultSelector()
streams.register(process.stdout, selectors.EVENT_READ, (stdout_path, 0))
streams.register(process.stderr, selectors.EVENT_READ, (stderr_path, 0))
exceeded = False
outputs = {
stdout_path: stdout_path.open("xb"),
stderr_path: stderr_path.open("xb"),
}
try:
while streams.get_map():
for key, _events in streams.select():
chunk = os.read(key.fileobj.fileno(), 64 * 1024)
path, written = key.data
if not chunk:
streams.unregister(key.fileobj)
key.fileobj.close()
continue
accepted = min(len(chunk), MAX_OUTPUT_BYTES - written)
if accepted > 0:
outputs[path].write(chunk[:accepted])
written += accepted
streams.modify(key.fileobj, selectors.EVENT_READ, (path, written))
if accepted != len(chunk) and not exceeded:
exceeded = True
try:
os.killpg(process.pid, signal.SIGKILL)
except ProcessLookupError:
pass
return process.wait(), exceeded
finally:
streams.close()
for output in outputs.values():
output.close()
def measured_artifacts(values):
result = []
labels = set()
for value in values:
label, separator, raw_path = value.partition("=")
if not separator or not label or label in labels:
raise ValueError("measured paths require unique LABEL=PATH values")
labels.add(label)
path = Path(raw_path)
if path.is_symlink() or not path.is_file():
raise ValueError("measured artifact must be a regular file")
result.append({
"label": label,
"bytes": path.stat().st_size,
"sha256": file_digest(path),
})
return result
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--profile", choices=("small", "medium", "provider"), required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--source-manifest", type=Path, action="append", default=[])
parser.add_argument("--database", type=Path)
parser.add_argument("--expanded-bytes", type=int)
parser.add_argument("--measured-path", action="append", default=[])
parser.add_argument("command", nargs=argparse.REMAINDER)
args = parser.parse_args()
if not args.command or args.command[0] != "--" or len(args.command) == 1:
parser.error("terminate options with -- and provide a command")
command = args.command[1:]
if args.output.exists():
raise FileExistsError("benchmark output already exists")
if args.expanded_bytes is not None and args.expanded_bytes < 0:
raise ValueError("expanded bytes cannot be negative")
sources = [read_manifest(path) for path in args.source_manifest]
before = database_counts(args.database)
args.output.mkdir(parents=True)
stdout_path = args.output / "stdout"
stderr_path = args.output / "stderr"
started_at = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
usage_before = resource.getrusage(resource.RUSAGE_CHILDREN)
started = time.monotonic()
exit_status, output_limit_exceeded = run_bounded(command, stdout_path, stderr_path)
wall_seconds = time.monotonic() - started
usage_after = resource.getrusage(resource.RUSAGE_CHILDREN)
after = database_counts(args.database)
stdout = bounded_file(stdout_path)
operation = None
if stdout is not None:
try:
operation = json.loads(stdout, object_pairs_hook=unique_object)
except (UnicodeDecodeError, json.JSONDecodeError, ValueError):
pass
fact_growth = after["facts"] - before["facts"]
report = {
"schema": "argand.site-benchmark/v1",
"profile": args.profile,
"started_at": started_at,
"hardware": hardware(),
"sources": sources,
"operation": {
"program": Path(command[0]).name,
"argument_vector_sha256": digest(b"\0".join(os.fsencode(item) for item in command)),
"exit_status": exit_status,
"output_limit_exceeded": output_limit_exceeded,
"stdout_sha256": file_digest(stdout_path),
"stderr_sha256": file_digest(stderr_path),
"result": operation,
},
"metrics": {
"wall_seconds": round(wall_seconds, 6),
"user_cpu_seconds": round(usage_after.ru_utime - usage_before.ru_utime, 6),
"system_cpu_seconds": round(usage_after.ru_stime - usage_before.ru_stime, 6),
"peak_rss_kib": usage_after.ru_maxrss,
"compressed_source_bytes": sum(source["compressed_bytes"] for source in sources),
"expanded_source_bytes": args.expanded_bytes,
"database_before": before,
"database_after": after,
"database_growth_bytes": after["bytes"] - before["bytes"],
"record_growth": after["records"] - before["records"],
"fact_growth": fact_growth,
"facts_per_second": round(fact_growth / wall_seconds, 3)
if fact_growth > 0 and wall_seconds > 0 else None,
"import_checkpoint_records": 256,
},
"artifacts": measured_artifacts(args.measured_path),
}
report_path = args.output / "REPORT.json"
with report_path.open("xb") as stream:
stream.write(json.dumps(report, indent=2, sort_keys=True).encode() + b"\n")
stream.flush()
os.fsync(stream.fileno())
directory = os.open(args.output, os.O_RDONLY | os.O_DIRECTORY)
try:
os.fsync(directory)
finally:
os.close(directory)
return exit_status
if __name__ == "__main__":
try:
sys.exit(main())
except (FileExistsError, OSError, ValueError) as error:
print(error, file=sys.stderr)
sys.exit(2)