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,126 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""快照当前主机侧可回滚现场:I210 高级属性、中断亲和、ecat 进程。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
LAB = os.path.join(ROOT, "lab", "skip_meter")
|
||||
|
||||
|
||||
def ps(cmd: str) -> str:
|
||||
r = subprocess.run(
|
||||
["powershell", "-NoProfile", "-Command", cmd],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
errors="replace",
|
||||
)
|
||||
return (r.stdout or "") + (("ERR:" + r.stderr) if r.stderr else "")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
os.makedirs(LAB, exist_ok=True)
|
||||
snap = {"ts": time.time(), "host": os.environ.get("COMPUTERNAME")}
|
||||
|
||||
snap["adapters"] = ps(
|
||||
"Get-NetAdapter | Select-Object Name,InterfaceDescription,LinkSpeed,Status,"
|
||||
"ifIndex,MacAddress | ConvertTo-Json -Compress"
|
||||
)
|
||||
# I210 specifically
|
||||
snap["i210"] = ps(
|
||||
"Get-NetAdapter | Where-Object {$_.InterfaceDescription -match 'I210'} | "
|
||||
"Select-Object Name,ifIndex,Status,LinkSpeed | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
# advanced properties (restore-able)
|
||||
snap["i210_adv"] = ps(
|
||||
"Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | "
|
||||
"Select-Object Name,DisplayName,DisplayValue,RegistryKeyword,RegistryValue | "
|
||||
"ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
# interrupt moderation / RSS / power
|
||||
for kw in (
|
||||
"*InterruptModeration",
|
||||
"*ReceiveBuffers",
|
||||
"*TransmitBuffers",
|
||||
"*EEE",
|
||||
"*EnergyEfficient",
|
||||
"*FlowControl",
|
||||
"*PriorityVLANTag",
|
||||
"*TCPChecksumOffload*",
|
||||
"*IPChecksumOffload*",
|
||||
"*VMQ",
|
||||
"*RSS",
|
||||
"*InterruptModerationRate",
|
||||
):
|
||||
snap[f"adv_{kw.strip('*').replace('*','_')}"] = ps(
|
||||
f"Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | "
|
||||
f"Where-Object {{$_.RegistryKeyword -like '{kw}'}} | "
|
||||
f"Select-Object RegistryKeyword,DisplayValue,RegistryValue | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
snap["power"] = ps(
|
||||
"Get-NetAdapterPowerManagement -Name '以太网 2' -ErrorAction SilentlyContinue | "
|
||||
"Select-Object Name,AllowComputerToTurnOffDevice,WakeOnMagicPacket,"
|
||||
"WakeOnPattern,DeviceSleepOnDisconnect | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
snap["ecat_proc"] = ps(
|
||||
"Get-Process ecat_native -ErrorAction SilentlyContinue | "
|
||||
"Select-Object Id,Path,StartTime,CPU,WorkingSet | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
snap["ecat_cmdline"] = ps(
|
||||
"Get-CimInstance Win32_Process -Filter \"Name='ecat_native.exe'\" | "
|
||||
"Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
# interrupt affinity via Get-NetAdapterInterrupt? not always available
|
||||
snap["msi_affinity"] = ps(
|
||||
"Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | "
|
||||
"Where-Object {$_.DisplayName -match 'Interrupt|Affinity|RSS|Moderation|Buffer|Energy|Green|Flow|Offload'} | "
|
||||
"Select-Object DisplayName,DisplayValue,RegistryKeyword | ConvertTo-Json -Compress"
|
||||
)
|
||||
|
||||
# CPU topology quick
|
||||
snap["cpu"] = ps(
|
||||
"$env:NUMBER_OF_PROCESSORS; (Get-CimInstance Win32_Processor | "
|
||||
"Select-Object Name,NumberOfCores,NumberOfLogicalProcessors | ConvertTo-Json -Compress)"
|
||||
)
|
||||
|
||||
out = os.path.join(LAB, f"host_snap_{int(time.time())}.json")
|
||||
with open(out, "w", encoding="utf-8") as f:
|
||||
json.dump(snap, f, ensure_ascii=False, indent=2)
|
||||
|
||||
# also human-readable restore snippet
|
||||
lines = []
|
||||
lines.append("# Host snapshot restore notes")
|
||||
lines.append(f"time={snap['ts']}")
|
||||
lines.append("## I210 adapter advanced (raw)")
|
||||
lines.append(snap.get("i210_adv", "")[:8000])
|
||||
lines.append("## power")
|
||||
lines.append(snap.get("power", "")[:4000])
|
||||
lines.append("## ecat cmdline")
|
||||
lines.append(snap.get("ecat_cmdline", "")[:2000])
|
||||
txt = os.path.join(LAB, f"host_snap_{int(snap['ts'])}.txt")
|
||||
with open(txt, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(lines))
|
||||
|
||||
print("I210:", snap.get("i210", "")[:500])
|
||||
print("CMDLINE:", snap.get("ecat_cmdline", "")[:800])
|
||||
print("ADV keys sample:")
|
||||
print(snap.get("msi_affinity", "")[:2500])
|
||||
print("WROTE", out)
|
||||
print("WROTE", txt)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user