77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
||
|
|
"""High vs RealTime 多轮 A/B,输出对比。结束后设为 --final 指定档。"""
|
||
|
|
import json, os, subprocess, sys, time
|
||
|
|
|
||
|
|
ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||
|
|
LAB = os.path.join(ROOT, "lab", "skip_meter")
|
||
|
|
|
||
|
|
def ecat_pid():
|
||
|
|
out = subprocess.check_output(
|
||
|
|
["powershell","-NoProfile","-Command","(Get-Process ecat_native).Id"],
|
||
|
|
text=True).strip()
|
||
|
|
return int(out.splitlines()[0])
|
||
|
|
|
||
|
|
def set_prio(level):
|
||
|
|
p = ecat_pid()
|
||
|
|
subprocess.check_output(
|
||
|
|
["powershell","-NoProfile","-Command",
|
||
|
|
f"$p=Get-Process -Id {p}; $p.PriorityClass='{level}'; $p.PriorityClass"],
|
||
|
|
text=True)
|
||
|
|
return level
|
||
|
|
|
||
|
|
def meter(tag, secs=12):
|
||
|
|
r = subprocess.run([sys.executable, os.path.join(ROOT,"scripts","skip_rate_meter.py"),
|
||
|
|
"--tag", tag, "--secs", str(secs)],
|
||
|
|
capture_output=True, text=True, encoding="utf-8", errors="replace")
|
||
|
|
files = sorted([f for f in os.listdir(LAB) if f.startswith(tag+"_") and f.endswith(".json")])
|
||
|
|
return json.load(open(os.path.join(LAB, files[-1]), encoding="utf-8"))
|
||
|
|
|
||
|
|
def row(level, data, n):
|
||
|
|
return {
|
||
|
|
"round": n, "level": level,
|
||
|
|
"late_per_s": data["late_per_s"], "skip_per_s": data["skip_per_s"],
|
||
|
|
"send_stall_frac": data["send_stall_frac"], "rx_stall_frac": data["rx_stall_frac"],
|
||
|
|
"achieved_hz": data["achieved_hz"], "n_late": data["n_late"],
|
||
|
|
"send_p90": (data.get("window_cyc_us") or {}).get("send",{}).get("p90"),
|
||
|
|
"work_p90": (data.get("window_cyc_us") or {}).get("work",{}).get("p90"),
|
||
|
|
}
|
||
|
|
|
||
|
|
def main():
|
||
|
|
final = "RealTime"
|
||
|
|
if len(sys.argv) > 1:
|
||
|
|
final = sys.argv[1]
|
||
|
|
rows = []
|
||
|
|
# A-B-A-B
|
||
|
|
seq = ["High","RealTime","High","RealTime"]
|
||
|
|
for i, lv in enumerate(seq, 1):
|
||
|
|
set_prio(lv)
|
||
|
|
time.sleep(1.0)
|
||
|
|
data = meter(f"ab_{lv}_{i}", 12)
|
||
|
|
r = row(lv, data, i)
|
||
|
|
rows.append(r)
|
||
|
|
print(r)
|
||
|
|
set_prio(final)
|
||
|
|
print("FINAL", final, "pid", ecat_pid())
|
||
|
|
# summary means
|
||
|
|
by = {}
|
||
|
|
for r in rows:
|
||
|
|
by.setdefault(r["level"], []).append(r)
|
||
|
|
means = {}
|
||
|
|
for lv, rs in by.items():
|
||
|
|
means[lv] = {
|
||
|
|
"n": len(rs),
|
||
|
|
"late_per_s_mean": round(sum(x["late_per_s"] for x in rs)/len(rs), 3),
|
||
|
|
"skip_per_s_mean": round(sum(x["skip_per_s"] for x in rs)/len(rs), 3),
|
||
|
|
"send_p90_mean": round(sum(x["send_p90"] or 0 for x in rs)/len(rs), 1),
|
||
|
|
"work_p90_mean": round(sum(x["work_p90"] or 0 for x in rs)/len(rs), 1),
|
||
|
|
}
|
||
|
|
print("MEANS", json.dumps(means, ensure_ascii=False, indent=2))
|
||
|
|
path = os.path.join(LAB, f"summary_ab_prio_{int(time.time())}.json")
|
||
|
|
json.dump({"rows": rows, "means": means, "final": final}, open(path,"w",encoding="utf-8"),
|
||
|
|
ensure_ascii=False, indent=2)
|
||
|
|
print("WROTE", path)
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|