4图×5发型=20行,每行4分辨率对比,steps=15,热数据。 80/80成功,0 OOM,峰值21.2GB(原图不缩放也未OOM)。 报告: static/bench3_report.html
100 lines
4.0 KiB
Python
100 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""分辨率对比测试:4图×5发型=20行,每行4种分辨率(不缩放/896/768/640),steps=15。
|
||
热数据:每个组合预热1次(丢弃)+正式1次。OOM的跳过记录为失败。
|
||
"""
|
||
import base64
|
||
import json
|
||
import os
|
||
import time
|
||
from pathlib import Path
|
||
|
||
import requests
|
||
|
||
API = "http://127.0.0.1:8187/api/v1/debug/grow-timing"
|
||
TOKEN = "dev-shared-secret-2026"
|
||
OUT = Path("/home/ubuntu/hair/benchmark_out/bench3")
|
||
OUT.mkdir(parents=True, exist_ok=True)
|
||
|
||
IMGS = [
|
||
("asdf", "/home/ubuntu/hair/image/asdf.jpg"),
|
||
("qwer", "/home/ubuntu/hair/image/qwer.jpg"),
|
||
("girl2", "/home/ubuntu/hair/image/girl_img/girl2.jpg"),
|
||
("girl5", "/home/ubuntu/hair/image/girl_img/girl5.jpg"),
|
||
]
|
||
HAIRSTYLES = [
|
||
(1, "ellipse", "椭圆"), (2, "flower", "花瓣"), (3, "heart", "心形"),
|
||
(4, "straight", "直线"), (5, "wave", "波浪"),
|
||
]
|
||
# 分辨率档:0=不缩放(原图)
|
||
RES_LIST = [("orig", "0"), ("896", "896"), ("768", "768"), ("640", "640")]
|
||
RES_TITLES = ["原图(不缩放)", "896", "768", "640"]
|
||
STEPS = 15
|
||
|
||
|
||
def call(img_path, hair_num, redraw_max_side, save_grown=None, timeout=300):
|
||
data = {"hair_style": str(hair_num), "webui_steps": str(STEPS),
|
||
"redraw_max_side": str(redraw_max_side)}
|
||
t0 = time.perf_counter()
|
||
try:
|
||
with open(img_path, "rb") as f:
|
||
r = requests.post(API, headers={"X-Internal-Token": TOKEN},
|
||
files={"image_file": (os.path.basename(img_path), f, "image/jpeg")},
|
||
data=data, timeout=timeout)
|
||
wall = time.perf_counter() - t0
|
||
j = r.json()
|
||
if j.get("code") != 0:
|
||
return {"ok": False, "error": j.get("message", "")[:80], "wall": wall}
|
||
d = j["data"]
|
||
hs = d["per_hairstyle"][0]
|
||
if save_grown and hs.get("grown_b64"):
|
||
b = hs["grown_b64"].split(",")[1] if "," in hs["grown_b64"] else hs["grown_b64"]
|
||
with open(save_grown, "wb") as gf:
|
||
gf.write(base64.b64decode(b))
|
||
return {
|
||
"ok": hs.get("ok", False), "wall": wall,
|
||
"total_ms": d["total_ms"], "swap_ms": hs.get("swap_ms"),
|
||
"comfy_ms": hs.get("comfyui_redraw_ms"),
|
||
"error": hs.get("error"),
|
||
}
|
||
except Exception as e:
|
||
return {"ok": False, "error": str(e)[:80], "wall": time.perf_counter() - t0}
|
||
|
||
|
||
def main():
|
||
rows = []
|
||
total = len(IMGS) * len(HAIRSTYLES) * len(RES_LIST) * 2
|
||
idx = 0
|
||
for ilabel, ipath in IMGS:
|
||
for hnum, hkey, hname in HAIRSTYLES:
|
||
cells = []
|
||
for (rlabel, rval), rtitle in zip(RES_LIST, RES_TITLES):
|
||
# 预热
|
||
idx += 1
|
||
print(f"[{idx}/{total}] 预热 {ilabel}|{hname}|{rtitle}", flush=True)
|
||
try:
|
||
call(ipath, hnum, rval, timeout=120)
|
||
except Exception:
|
||
pass # 预热失败(可能OOM)不中断
|
||
# 正式
|
||
idx += 1
|
||
save = OUT / f"{ilabel}_{hkey}_{rlabel}.jpg"
|
||
print(f"[{idx}/{total}] 正式 {ilabel}|{hname}|{rtitle}", flush=True)
|
||
r = call(ipath, hnum, rval, save_grown=save, timeout=300)
|
||
r["res_label"] = rlabel; r["res_title"] = rtitle
|
||
r["grown_path"] = str(save) if r.get("ok") else None
|
||
status = f"{r.get('total_ms')}ms" if r.get("ok") else f"FAIL:{r.get('error','')[:30]}"
|
||
print(f" -> {status}", flush=True)
|
||
cells.append(r)
|
||
rows.append({"img": ilabel, "img_path": ipath,
|
||
"hair_num": hnum, "hair_key": hkey, "hair_name": hname,
|
||
"cells": cells})
|
||
with open(OUT / "results.json", "w", encoding="utf-8") as f:
|
||
json.dump({"res_titles": RES_TITLES, "rows": rows}, f, ensure_ascii=False, indent=2)
|
||
ok = sum(1 for row in rows for c in row["cells"] if c.get("ok"))
|
||
print(f"\n✓ 完成: {ok}/{len(rows)*len(RES_LIST)} 成功 -> {OUT/'results.json'}", flush=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|