Files
MARTe-Integrated-Components/Test/E2E/suite/proc_perf.py
T

77 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""
proc_perf.py — Snapshot a live process's CPU time and peak memory from /proc.
Usage: proc_perf.py <pid> <label> <out.json>
Reads /proc/<pid>/stat (utime+stime, in clock ticks) and /proc/<pid>/status
(VmHWM = peak resident set, VmRSS = current) *while the process is alive* — peak
RSS is only legible before the process exits, so the orchestrator calls this just
before tearing the stack down. Emits a small JSON record:
{"label": ..., "avail": true, "cpu_s": float, "peak_rss_kb": int,
"rss_kb": int, "threads": int}
If the process is already gone, writes {"label": ..., "avail": false}.
"""
import json
import os
import sys
def _clk_tck():
try:
return os.sysconf("SC_CLK_TCK") or 100
except (ValueError, OSError):
return 100
def snapshot(pid):
stat_p = f"/proc/{pid}/stat"
status_p = f"/proc/{pid}/status"
if not os.path.exists(stat_p):
return {"avail": False}
try:
with open(stat_p) as f:
raw = f.read()
# The comm field is parenthesised and may contain spaces/parens, so split
# on the final ')': everything after it is space-separated, with state as
# the first token. utime/stime are overall fields 14/15 → indices 11/12
# of the post-')' tokens (pid + comm consumed before the split).
after = raw[raw.rindex(")") + 1:].split()
utime = int(after[11])
stime = int(after[12])
cpu_s = (utime + stime) / float(_clk_tck())
rec: dict = {"avail": True, "cpu_s": cpu_s}
with open(status_p) as f:
for line in f:
if line.startswith("VmHWM:"):
rec["peak_rss_kb"] = int(line.split()[1])
elif line.startswith("VmRSS:"):
rec["rss_kb"] = int(line.split()[1])
elif line.startswith("Threads:"):
rec["threads"] = int(line.split()[1])
return rec
except (OSError, ValueError, IndexError):
return {"avail": False}
def main():
if len(sys.argv) != 4:
print("usage: proc_perf.py <pid> <label> <out.json>", file=sys.stderr)
sys.exit(2)
pid, label, out = sys.argv[1], sys.argv[2], sys.argv[3]
rec = snapshot(pid)
rec["label"] = label
with open(out, "w") as f:
json.dump(rec, f)
if rec.get("avail"):
print(f"perf {label}: cpu={rec.get('cpu_s', 0):.2f}s "
f"peakRSS={rec.get('peak_rss_kb', 0)/1024:.1f}MB")
else:
print(f"perf {label}: unavailable (process gone)")
if __name__ == "__main__":
main()