4图×2发型×(3步数档+3分辨率档) 热数据对比,48/48成功,0 OOM,峰值20.6GB。 - benchmark_steps_res.py: 测试脚本(预热+正式取热数据) - benchmark_steps_res_report.py: 报告生成 - static/bench2_report.html: 对比报告 - static/bench2/: 48张结果图 结论: B维度 steps10→20 swap 3.0s→3.9s; C维度 res640比896省3s(comfy 4.3s vs 7.3s)
158 lines
7.1 KiB
Python
158 lines
7.1 KiB
Python
#!/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"""<tr>
|
||
<td>{r['img']}</td><td>{r['hair_name']}</td><td>{r['steps']}</td>
|
||
<td>{r.get('swap_ms','?')}</td><td>{r.get('comfy_ms','?')}</td><td>{r.get('total_ms','?')}</td>
|
||
<td>{f'<img src="{src}" loading="lazy">' if src else '⚠'}</td></tr>""")
|
||
|
||
# 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"""<tr>
|
||
<td>{r['img']}</td><td>{r['hair_name']}</td><td>{r['res']}</td>
|
||
<td>{r.get('swap_ms','?')}</td><td>{r.get('comfy_ms','?')}</td><td>{r.get('total_ms','?')}</td>
|
||
<td>{f'<img src="{src}" loading="lazy">' if src else '⚠'}</td></tr>""")
|
||
|
||
def bar_row(label, val, max_val, color, unit="ms"):
|
||
pct = max(1, val / max_val * 100) if max_val else 0
|
||
return f'<div class="step-row"><div class="step-name">{label}</div>' \
|
||
f'<div class="step-bar-wrap"><div class="step-bar {color}" style="width:{pct}%">{val}{unit}</div></div>' \
|
||
f'<div class="step-time">{val}{unit}</div></div>'
|
||
|
||
# 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"""<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>swap步数 + 重绘分辨率 对比报告</title>
|
||
<style>
|
||
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
||
body {{ font-family: -apple-system, "Segoe UI", sans-serif; background: #f5f5f5; padding: 16px; color: #333; }}
|
||
h1 {{ font-size: 20px; margin-bottom: 4px; }}
|
||
h2 {{ font-size: 16px; margin: 20px 0 10px; }}
|
||
.subtitle {{ color: #888; font-size: 12px; margin-bottom: 14px; }}
|
||
.card {{ background: #fff; border-radius: 10px; box-shadow: 0 1px 4px rgba(0,0,0,.06); margin-bottom: 16px; overflow: hidden; }}
|
||
.card-header {{ font-weight: 700; font-size: 14px; padding: 12px 18px; border-bottom: 1px solid #f0f0f0; background: #fafafa; }}
|
||
.card-body {{ padding: 18px; }}
|
||
.summary-grid {{ display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }}
|
||
.step-row {{ display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 13px; }}
|
||
.step-name {{ width: 100px; flex-shrink: 0; font-weight: 600; }}
|
||
.step-bar-wrap {{ flex: 1; background: #f3f4f6; border-radius: 4px; height: 24px; min-width: 200px; }}
|
||
.step-bar {{ height: 100%; border-radius: 4px; display: flex; align-items: center; padding-left: 8px; color: #fff; font-size: 11px; font-weight: 600; min-width: 2px; }}
|
||
.step-time {{ width: 70px; text-align: right; font-weight: 600; flex-shrink: 0; font-variant-numeric: tabular-nums; }}
|
||
.c-swap {{ background: #f59e0b; }} .c-comfy {{ background: #ef4444; }} .c-total {{ background: #2563eb; }}
|
||
table {{ border-collapse: collapse; width: 100%; font-size: 12px; }}
|
||
th, td {{ border: 1px solid #eee; padding: 5px 8px; text-align: center; }}
|
||
th {{ background: #f9fafb; font-weight: 600; position: sticky; top: 0; }}
|
||
td img {{ max-height: 100px; max-width: 80px; border-radius: 4px; }}
|
||
.scroll {{ max-height: 400px; overflow: auto; }}
|
||
.note {{ background: #fef3c7; border-radius: 8px; padding: 10px 14px; font-size: 12px; color: #92400e; margin-top: 10px; }}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>📊 swap步数 + 重绘分辨率 对比报告</h1>
|
||
<p class="subtitle">4图(asdf/qwer/girl2/girl5) × 2发型(波浪/心形) · 热数据(预热后取第2次) · 48/48成功 · 峰值20.6GB · 0 OOM</p>
|
||
|
||
<div class="note">💡 结论速览: B维度 steps 10→20 swap从3.0s→3.9s(每步省~90ms);C维度 res 640比896省3s(comfy 4.3s vs 7.3s),1024与896接近。</div>
|
||
|
||
<h2>B维度:swap步数对比(分辨率固定896)</h2>
|
||
<div class="summary-grid">
|
||
<div class="card"><div class="card-header">swap 耗时(越低越快)</div><div class="card-body">{b_bars}</div></div>
|
||
<div class="card"><div class="card-header">总耗时(越低越快)</div><div class="card-body">{b_total_bars}</div></div>
|
||
</div>
|
||
|
||
<h2>C维度:重绘分辨率对比(steps固定15)</h2>
|
||
<div class="summary-grid">
|
||
<div class="card"><div class="card-header">ComfyUI重绘 耗时(越低越快)</div><div class="card-body">{c_bars}</div></div>
|
||
<div class="card"><div class="card-header">总耗时(越低越快)</div><div class="card-body">{c_total_bars}</div></div>
|
||
</div>
|
||
|
||
<h2>B维度明细(每图每发型每步数)</h2>
|
||
<div class="card"><div class="scroll"><table>
|
||
<tr><th>图片</th><th>发型</th><th>steps</th><th>swap(ms)</th><th>comfy(ms)</th><th>总(ms)</th><th>结果</th></tr>
|
||
{"".join(b_rows)}
|
||
</table></div></div>
|
||
|
||
<h2>C维度明细(每图每发型每分辨率)</h2>
|
||
<div class="card"><div class="scroll"><table>
|
||
<tr><th>图片</th><th>发型</th><th>res</th><th>swap(ms)</th><th>comfy(ms)</th><th>总(ms)</th><th>结果</th></tr>
|
||
{"".join(c_rows)}
|
||
</table></div></div>
|
||
</body>
|
||
</html>"""
|
||
|
||
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()
|