feat(ecat): 启动后把 ecat_native 提到 RealTime;跳拍优化实验脚本与报告
- esp32_server: Popen 后外部 SetPriorityClass(RT/High),native 自设会被钳成 High - 入库 skip_* 标定/实验脚本与 REPORT_ecat_skip_opt_20260917 - 前端 WIP:layout/app/polling/boot_ecat/index - 不含 lab/skip_meter 原始采样与 preview 截图
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""进程优先级对照:不高/RealTime,各采 skip rate。不改网卡、不碰固件。"""
|
||||
import json, os, subprocess, sys, time, urllib.request
|
||||
|
||||
ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
LAB = os.path.join(ROOT, "lab", "skip_meter")
|
||||
BASE = "http://127.0.0.1:8090"
|
||||
|
||||
def post(path, body=None):
|
||||
data = json.dumps(body or {}).encode()
|
||||
req = urllib.request.Request(BASE+path, data=data, headers={"Content-Type":"application/json"})
|
||||
with urllib.request.urlopen(req, timeout=5) as r:
|
||||
return json.loads(r.read().decode())
|
||||
|
||||
def pid():
|
||||
return post("/api/native/health") # health has no pid; use process name
|
||||
# fallback below
|
||||
|
||||
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()
|
||||
cmd = f"$p=Get-Process -Id {p}; $p.PriorityClass='{level}'; $p.PriorityClass"
|
||||
return subprocess.check_output(["powershell","-NoProfile","-Command",cmd], text=True).strip()
|
||||
|
||||
def meter(tag, secs=16):
|
||||
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")])
|
||||
data = json.load(open(os.path.join(LAB, files[-1]), encoding="utf-8")) if files else None
|
||||
return data, r.stdout
|
||||
|
||||
def main():
|
||||
p = ecat_pid()
|
||||
print("ecat pid", p)
|
||||
cur = subprocess.check_output(
|
||||
["powershell","-NoProfile","-Command", f"(Get-Process -Id {p}).PriorityClass"],
|
||||
text=True).strip()
|
||||
print("current PriorityClass", cur)
|
||||
|
||||
results = []
|
||||
for level in ("High", "RealTime"):
|
||||
print(f"\n=== set {level} ===")
|
||||
try:
|
||||
print(set_prio(level))
|
||||
except Exception as e:
|
||||
print("set fail", e)
|
||||
continue
|
||||
time.sleep(1.5)
|
||||
data, out = meter(f"prio_{level}", 16)
|
||||
if data:
|
||||
row = {"level": level, "late_per_s": data["late_per_s"], "skip_per_s": data["skip_per_s"],
|
||||
"late_frac_pct": data["late_frac_pct"], "send_stall_frac": data["send_stall_frac"],
|
||||
"rx_stall_frac": data["rx_stall_frac"], "achieved_hz": data["achieved_hz"],
|
||||
"n_late": data["n_late"]}
|
||||
results.append(row)
|
||||
print("ROW", row)
|
||||
print(out[-800:] if out else "")
|
||||
|
||||
# restore High (safe default; pdo thread already TIME_CRITICAL)
|
||||
try:
|
||||
print("restore High")
|
||||
print(set_prio("High"))
|
||||
except Exception as e:
|
||||
print("restore fail", e)
|
||||
|
||||
path = os.path.join(LAB, f"summary_prio_{int(time.time())}.json")
|
||||
json.dump({"results": results, "original": cur}, open(path,"w",encoding="utf-8"), ensure_ascii=False, indent=2)
|
||||
print("WROTE", path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user