#!/usr/bin/env python3 # -*- coding: utf-8 -*- """生成 swap步数 + 重绘分辨率 对比报告 HTML。""" import json import os from collections import defaultdict from pathlib import Path OUT = Path("/home/ubuntu/hair/benchmark_out/bench2") RESULTS = OUT / "results.json" HTML = OUT / "report.html" def img_src(path): if not path or not os.path.isfile(path): return None # benchmark_out/bench2/xxx.jpg -> bench2/xxx.jpg (报告在 static/ 下部署时调整) p = str(path) return "bench2/" + os.path.basename(p) def main(): d = json.load(open(RESULTS, encoding="utf-8")) b_data = d["B_steps"] # steps 对比 c_data = d["C_res"] # 分辨率对比 # B维度聚合 by_steps = defaultdict(list) for r in b_data: by_steps[r["steps"]].append(r) b_summary = [] for s in sorted(by_steps): rs = by_steps[s] b_summary.append({ "label": f"steps={s}", "n": len(rs), "swap": sum(r["swap_ms"] for r in rs) // len(rs), "total": sum(r["total_ms"] for r in rs) // len(rs), }) # C维度聚合 by_res = defaultdict(list) for r in c_data: by_res[r["res"]].append(r) c_summary = [] for res in sorted(by_res): rs = by_res[res] c_summary.append({ "label": f"res={res}", "n": len(rs), "comfy": sum(r["comfy_ms"] for r in rs) // len(rs), "total": sum(r["total_ms"] for r in rs) // len(rs), }) # B维度明细行(每图每发型每步数) b_rows = [] for r in sorted(b_data, key=lambda x: (x["img"], x["hair"], x["steps"])): src = img_src(r.get("grown_path")) b_rows.append(f""" {r['img']}{r['hair_name']}{r['steps']} {r.get('swap_ms','?')}{r.get('comfy_ms','?')}{r.get('total_ms','?')} {f'' if src else '⚠'}""") # C维度明细行 c_rows = [] for r in sorted(c_data, key=lambda x: (x["img"], x["hair"], x["res"])): src = img_src(r.get("grown_path")) c_rows.append(f""" {r['img']}{r['hair_name']}{r['res']} {r.get('swap_ms','?')}{r.get('comfy_ms','?')}{r.get('total_ms','?')} {f'' if src else '⚠'}""") def bar_row(label, val, max_val, color, unit="ms"): pct = max(1, val / max_val * 100) if max_val else 0 return f'
{label}
' \ f'
{val}{unit}
' \ f'
{val}{unit}
' # B维度汇总条形图 b_max_swap = max(s["swap"] for s in b_summary) b_bars = "".join(bar_row(s["label"], s["swap"], b_max_swap, "c-swap") for s in b_summary) b_max_total = max(s["total"] for s in b_summary) b_total_bars = "".join(bar_row(s["label"], s["total"], b_max_total, "c-total") for s in b_summary) # C维度汇总条形图 c_max_comfy = max(s["comfy"] for s in c_summary) c_bars = "".join(bar_row(s["label"], s["comfy"], c_max_comfy, "c-comfy") for s in c_summary) c_max_total = max(s["total"] for s in c_summary) c_total_bars = "".join(bar_row(s["label"], s["total"], c_max_total, "c-total") for s in c_summary) html = f""" swap步数 + 重绘分辨率 对比报告

📊 swap步数 + 重绘分辨率 对比报告

4图(asdf/qwer/girl2/girl5) × 2发型(波浪/心形) · 热数据(预热后取第2次) · 48/48成功 · 峰值20.6GB · 0 OOM

💡 结论速览: B维度 steps 10→20 swap从3.0s→3.9s(每步省~90ms);C维度 res 640比896省3s(comfy 4.3s vs 7.3s),1024与896接近。

B维度:swap步数对比(分辨率固定896)

swap 耗时(越低越快)
{b_bars}
总耗时(越低越快)
{b_total_bars}

C维度:重绘分辨率对比(steps固定15)

ComfyUI重绘 耗时(越低越快)
{c_bars}
总耗时(越低越快)
{c_total_bars}

B维度明细(每图每发型每步数)

{"".join(b_rows)}
图片发型stepsswap(ms)comfy(ms)总(ms)结果

C维度明细(每图每发型每分辨率)

{"".join(c_rows)}
图片发型resswap(ms)comfy(ms)总(ms)结果
""" with open(HTML, "w", encoding="utf-8") as f: f.write(html) print(f"✓ 报告: {HTML} ({HTML.stat().st_size // 1024} KB)") if __name__ == "__main__": main()