mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-02 01:37:32 +08:00
* docs: record regression audit and validation * test: cover audited call and extraction regressions * test: cover audited calls and selector guards * test: cover audited calls and selector guards * test: cover audited calls and selector guards * test: cover audited calls and selector guards * test: cover audited calls and selector guards * fix: retain qualified call sites and restore language-specific getters * fix: resolve typed calls and bound store actions * fix: retain qualified call sites in the native kernel * docs: explain restored call and Steps coverage * test: isolate watchdog and cover imported store aliases * refactor: expose import lookup through resolver context * refactor: remove import resolver cycle * test: canonicalize Claude config temp paths * docs: record review fixes and large TypeScript timings * test: cover store cache edits and document verification * perf: cache per-file store eligibility * fix: observe large benchmarks without a wall timeout * docs: explain completed indexing benchmarks docs: explain completed indexing benchmarks
92 lines
3.7 KiB
Python
92 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Observe one owned benchmark child on Linux, without a wall-clock timeout.
|
|
|
|
Usage: python3 observe-index.py NEW_RUN_DIR -- node measure-index.cjs ENGINE FIXTURE NEW_RUN_DIR native
|
|
The child retains the caller's environment/affinity. No host settings are changed.
|
|
"""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
|
|
def read(path):
|
|
try:
|
|
return Path(path).read_text()
|
|
except (FileNotFoundError, PermissionError, ProcessLookupError):
|
|
return None
|
|
|
|
|
|
def sample(pid):
|
|
tasks = {}
|
|
try:
|
|
for task in Path(f'/proc/{pid}/task').iterdir():
|
|
tasks[task.name] = {name: read(task / name) for name in ('stat', 'schedstat', 'wchan')}
|
|
except (FileNotFoundError, ProcessLookupError):
|
|
pass
|
|
# Both common cgroup layouts; unavailable counters are recorded as null.
|
|
paths = [
|
|
'/proc/stat', '/proc/meminfo', '/proc/loadavg', '/proc/diskstats',
|
|
'/proc/pressure/cpu', '/proc/pressure/io', '/proc/pressure/memory',
|
|
'/sys/fs/cgroup/cpu.stat', '/sys/fs/cgroup/cpu.max',
|
|
'/sys/fs/cgroup/memory.current', '/sys/fs/cgroup/memory.max',
|
|
'/sys/fs/cgroup/cpu,cpuacct/cpu.stat',
|
|
'/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us',
|
|
'/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us',
|
|
'/sys/fs/cgroup/memory/memory.usage_in_bytes',
|
|
'/sys/fs/cgroup/memory/memory.limit_in_bytes',
|
|
]
|
|
return {'epochMs': time.time() * 1000,
|
|
'process': {name: read(f'/proc/{pid}/{name}') for name in ('stat', 'status', 'io')},
|
|
'threads': tasks, 'host': {path: read(path) for path in paths}}
|
|
|
|
|
|
def main():
|
|
if sys.platform != 'linux' or len(sys.argv) < 4 or sys.argv[2] != '--':
|
|
raise SystemExit(__doc__)
|
|
out = Path(sys.argv[1]).resolve()
|
|
out.mkdir(parents=True, exist_ok=False) # Preserve completed/interrupted runs.
|
|
argv = sys.argv[3:]
|
|
command = {'argv': argv, 'startedEpochMs': time.time() * 1000,
|
|
'affinity': sorted(os.sched_getaffinity(0)), 'wallTimeout': None}
|
|
command_path = out / 'command.json'
|
|
command_path.write_text(json.dumps(command, indent=2))
|
|
start = time.monotonic()
|
|
with (out / 'console.log').open('w') as log, (out / 'resources.ndjson').open('w') as resources:
|
|
# Inherit the foreground process group: Ctrl-C reaches this owned child
|
|
# too. Never signal a PID discovered outside this invocation.
|
|
child = subprocess.Popen(argv, stdout=log, stderr=subprocess.STDOUT)
|
|
command['pid'] = child.pid
|
|
command_path.write_text(json.dumps(command, indent=2))
|
|
next_notice = start
|
|
try:
|
|
while child.poll() is None:
|
|
resources.write(json.dumps(sample(child.pid)) + '\n')
|
|
resources.flush()
|
|
now = time.monotonic()
|
|
if now >= next_notice:
|
|
print(f'Benchmark PID {child.pid}: {now-start:.0f}s elapsed; progress in {out}', flush=True)
|
|
next_notice = now + 30
|
|
time.sleep(2)
|
|
except BaseException:
|
|
# Record an explicit interrupted outcome, even when no final result
|
|
# exists. Give only our child a chance to stop, then reap it.
|
|
child.terminate()
|
|
try:
|
|
child.wait(timeout=10)
|
|
except subprocess.TimeoutExpired:
|
|
child.kill()
|
|
child.wait()
|
|
command['interrupted'] = True
|
|
raise
|
|
finally:
|
|
command.update(exit=child.poll(), wallSec=time.monotonic()-start)
|
|
command_path.write_text(json.dumps(command, indent=2))
|
|
return child.returncode
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|