11 KiB
目标:所有接口 < 10 秒 — 三个优化方案
日期:2026-07-18 基准数据(优化1+2后轮换测试 5轮×4接口)
当前性能基线
| 接口 | 平均 | 最快 | 最慢 | 目标 | 差距 |
|---|---|---|---|---|---|
| 接口1-测量 | 0.1s | 0.1s | 0.1s | <10s | ✅ 已达标 |
| 接口2-女-椭圆 | 17.6s | 10.0s | 19.7s | <10s | -7.6s |
| 接口2-男-椭圆 | 8.1s | 7.9s | 8.4s | <10s | ✅ 已达标(余量小) |
| 接口3-B端生发 | 22.9s | 22.6s | 23.3s | <10s | -12.9s |
根因分析
ComfyUI 模型反复换出(最大瓶颈)
ComfyUI 服务端日志(journalctl -u comfyui)揭示了根因:
12:17:14 model_type FLUX
12:17:16 loaded completely; 17421 MB usable, 15622 MB loaded ← 全量加载(15.6GB)
12:17:16 Requested to load Flux2
12:17:23 Unloaded partially: 11904 MB freed, 3718 MB remains ← 部分卸载
12:17:24 loaded completely; 11832 MB usable, 8996 MB loaded ← 重新加载(8.9GB)
12:17:27 VAE loaded
12:17:29 Requested to load Flux2 ← 男性复用(快)
12:17:31 loaded completely; 11671 MB usable, 8996 MB loaded ← 已加载,6s完成
12:17:43 Unloaded partially: 8996 MB freed, 0.04 MB remains ← 全部卸载!
12:17:45 loaded completely; 17567 MB usable, 15622 MB loaded ← 全量重载(15.6GB)
12:17:52 Unloaded partially: 11904 MB freed, 3718 MB remains ← 再次部分卸载
12:17:54 loaded completely; 11814 MB usable, 8996 MB loaded ← 再次重载(8.9GB)
12:17:58 接口3 完成(21.5s)
ComfyUI 在每次执行后都会卸载模型,下次执行时重新加载。 模型加载耗时 ~8-15s,是接口3和接口2女超时的主因。
显存分布(32GB GPU)
| 进程 | 显存 | 说明 |
|---|---|---|
| ComfyUI (Flux-2) | ~10-15 GB | 动态加载/卸载 |
| hair_service_sd | ~8 GB | GAN 模型常驻 |
| SD WebUI | ~3.2 GB | SD1.5 + ControlNet |
| Hair 服务 | ~0.7 GB | uvicorn + 模型 |
| 合计 | ~22-27 GB | 仅剩 5-10 GB 可用 |
显存不足导致 ComfyUI 无法常驻完整的 Flux-2 模型(~15.6GB 全量或 ~9GB FP8)。
耗时拆解
接口3(22.9s):
ComfyUI 模型加载: ~15s ← 根因
ComfyUI 推理(steps=6): ~6s
预处理(人脸+SegFormer+划线): ~1.6s
接口2女(17.6s):
ComfyUI 模型加载: ~10s ← 根因(模型被接口3卸载后需重载)
ComfyUI 推理(steps=4): ~4s
swapHair HTTP: ~4.6s
预处理(extract_context): ~1.5s(优化2后 SegFormer 只跑一次)
接口2男(8.1s):
ComfyUI 推理(steps=6): ~6s
预处理: ~2s
(模型常被前一个女性接口加载好,所以无重载开销)
方案 A:释放显存给 ComfyUI(最小改动)
核心思路
ComfyUI 需要 ~15.6GB 显存才能全量加载 Flux-2。当前被 hair_service_sd(8GB)和 SD WebUI(3.2GB)挤占。如果释放足够显存,ComfyUI 就能常驻模型,消除反复加载。
具体措施
A1. 接口3不依赖 hair_service_sd
接口3 不调用 change_hair:8801 的 swapHair。但 hair_service_sd 的所有 GAN 模型(8GB)常驻显存只为接口2女服务。
方案:将 hair_service_sd 改为按需启动/停止:
- 接口2女调用前启动 hair_service_sd
- 接口2女完成后停止 hair_service_sd(释放 8GB)
- 接口3和接口2男不启动 hair_service_sd
释放:8 GB → ComfyUI 可用显存从 ~5GB 增至 ~13GB
A2. 接口2女改为先启动 hair_service_sd → swapHair → 停止 → 再调 ComfyUI
接口2女流程:
1. 启动 hair_service_sd (8s) ← 可预热
2. swapHair (4.6s)
3. 停止 hair_service_sd → 释放 8GB
4. ComfyUI 重绘 (4-6s, 模型常驻)
总: ~17s → 仍有问题
问题:hair_service_sd 启动需要 8s(加载全部 GAN),反而增加耗时。
A3. 停止 SD WebUI(3.2GB)
SD WebUI 只被 change_hair 的 swapHair 使用(接口2女)。如果接口2女改用其他方案(见方案B),可以完全停止 SD WebUI。
释放:3.2 GB
A4. 总释放和预期效果
| 措施 | 释放 | ComfyUI 可用 |
|---|---|---|
| 当前 | — | ~5-10 GB |
| A1 (停 hair_service_sd) | +8 GB | ~13-18 GB |
| A3 (停 SD WebUI) | +3.2 GB | ~16-21 GB |
| 合计 | +11.2 GB | ~16-21 GB |
Flux-2 全量 15.6GB,释放后 ComfyUI 可常驻模型。
预期耗时
| 接口 | 当前 | 优化后 | 达标 |
|---|---|---|---|
| 接口1 | 0.1s | 0.1s | ✅ |
| 接口2-女 | 17.6s | ~11s (swapHair 4.6s + ComfyUI 4s + 预处理 1.5s + 启停 1s) | ❌ 差1s |
| 接口2-男 | 8.1s | ~8s | ✅ |
| 接口3 | 22.9s | ~8s (ComfyUI 6s + 预处理 1.6s) | ✅ |
优点
- 改动最小:主要改服务启停逻辑
- 不影响算法质量
- 不需要换 torch 版本
缺点
- 接口2女仍可能超 10s(swapHair 4.6s 是硬瓶颈)
- hair_service_sd 启停增加系统复杂度
- 需要精确的显存管理
方案 B:统一工作流 + 降 steps(中等改动)
核心思路
两个工作流(0716add-hair-api.json 27节点 vs add_hair.json 29节点)加载相同模型但参数不同(steps=4 vs steps=6),切换时触发 ComfyUI 重新初始化。统一为一个工作流 + 降低 steps 可消除切换开销并加速推理。
具体措施
B1. 统一为单一工作流
将 add_hair.json 的 steps 从 6 降到 4,与 0716add-hair-api.json 一致。然后所有接口都用同一个工作流。
改动:
add_hair.json: KSampler steps 6 → 4- 接口2男和接口3统一用修改后的
add_hair.json - 接口2女也改用
add_hair.json(不再用0716add-hair-api.json)
效果:ComfyUI 不再在工作流间切换,模型可常驻。
B2. 进一步降低 steps 到 2
Flux-2 模型在 steps=2 时仍能生成合理结果(需质量验证)。
| steps | 单次推理 | 质量 |
|---|---|---|
| 6 | ~6s | 最好 |
| 4 | ~4s | 好 |
| 2 | ~2s | 可接受(需验证) |
B3. 接口2女去 swapHair(可选但关键)
swapHair 调 change_hair:8801 → webui:57860 SD1.5 img2img,耗时 4.6s。如果去掉 swapHair:
- 女性直接用原图 + 遮罩 → ComfyUI Flux-2 重绘
- 省去 4.6s + 不需要启动 hair_service_sd + SD WebUI
- 释放 ~11.2GB 显存给 ComfyUI
但:swapHair 是换发型功能,去掉后女性发型会不同。需要确认产品是否接受。
预期耗时
| 接口 | 当前 | B1(steps=4) | B2(steps=2) | B3(去swapHair) |
|---|---|---|---|---|
| 接口2-女 | 17.6s | ~10s | ~8s | ~6s |
| 接口2-男 | 8.1s | ~6s | ~4s | ~4s |
| 接口3 | 22.9s | ~8s | ~6s | ~6s |
优点
- 消除工作流切换开销
- 降低推理时间
- 可与方案A叠加
缺点
- steps 降低可能影响质量(需验证)
- 去 swapHair 改变女性发型效果
- 需要修改工作流 JSON 和服务代码
方案 C:ComfyUI 预热 + 模型常驻(系统级优化)
核心思路
通过 ComfyUI API 和配置,让 Flux-2 模型在启动后常驻显存,不执行后自动卸载。结合预热请求,确保每次调用时模型已在显存。
具体措施
C1. 配置 ComfyUI 保持模型加载
ComfyUI 有 --reserve-vram 和 --gpu-only 参数控制 VRAM 管理:
# 启动 ComfyUI 时禁用模型卸载
python main.py --listen --gpu-only --reserve-vram 0
--gpu-only:禁止将模型卸载到 CPU(保持 GPU 常驻)--reserve-vram 0:不预留 VRAM(最大化模型可用空间)
前提:需要释放足够显存(结合方案A的A1/A3)。
C2. ComfyUI 预热请求
在 hair 服务启动时,发送一个空请求给 ComfyUI,触发模型加载:
# hair 服务启动后
comfyui.warmup() # 发送最小工作流,触发 Flux-2 加载到 VRAM
效果:第一次请求不再需要等待模型加载。
C3. 停止其他占用显存的服务
与方案A结合:
- 停止 hair_service_sd(释放 8GB)
- 停止 SD WebUI(释放 3.2GB)
- 仅保留 ComfyUI + Hair 服务
总可用显存:32GB - 0.7GB(Hair) = ~31GB → 足以常驻 Flux-2(15.6GB)
C4. ComfyUI 模型管理优化
设置环境变量:
export COMFYUI_MODEL_KEEP=true # 保持模型加载
或在 ComfyUI 的 extra_model_paths.yaml 和 comfyui/config.yaml 中配置模型缓存策略。
C5. 接口2女 swapHair 异步化
swapHair(4.6s)是接口2女的独立瓶颈。改为异步流水线:
1. 接收请求 → 异步调 swapHair
2. 同时开始预处理(extract_context + 遮罩)
3. swapHair 完成 + 预处理完成 → 合并
4. ComfyUI 重绘
效果:swapHair 4.6s 与预处理 1.5s 并行,省 1.5s。
预期耗时
| 接口 | 当前 | C方案 |
|---|---|---|
| 接口1 | 0.1s | 0.1s |
| 接口2-女 | 17.6s | ~9s (swapHair 4.6s ∥ 预处理 1.5s + ComfyUI 4s) |
| 接口2-男 | 8.1s | ~6s (ComfyUI 4s + 预处理 2s) |
| 接口3 | 22.9s | ~6s (ComfyUI 4s + 预处理 1.6s) |
优点
- 从根本上解决模型换出问题
- 效果最稳定(模型常驻后不再有抖动)
- 可与方案B叠加(steps 降到2则接口2女 ~6s)
缺点
- 需要停掉 hair_service_sd 和 SD WebUI(影响其他功能)
- 接口2女仍依赖 swapHair(4.6s)
- ComfyUI 配置改动需验证不影响稳定性
--gpu-only在显存不足时可能导致 OOM 崩溃
三方案对比
| 维度 | 方案A(释放显存) | 方案B(统一工作流) | 方案C(模型常驻) |
|---|---|---|---|
| 改动量 | 小 | 中 | 中-大 |
| 接口2女 | ~11s ❌ | ~8s ✅ | ~9s ✅ |
| 接口3 | ~8s ✅ | ~6s ✅ | ~6s ✅ |
| 接口2男 | ~8s ✅ | ~4s ✅ | ~6s ✅ |
| 质量 | 不变 | 需验证 | 不变 |
| 风险 | 低 | 中(质量) | 中(OOM) |
| 可叠加 | ✅ | ✅ | ✅ |
我的建议
推荐:B + C 组合(统一工作流 + 模型常驻)
理由:
- 方案C 从根本上解决模型换出(最大瓶颈),但需要停掉 hair_service_sd 和 SD WebUI
- 方案B 降低 steps 到 2-4,进一步减少推理时间
- 方案B的B3(去swapHair) 是接口2女达标的关键:去掉 swapHair 后不再需要 hair_service_sd 和 SD WebUI,为方案C释放显存
- 组合后所有接口都能稳定在 6-8s
关键决策点:接口2女是否可以去掉 swapHair(换发型)?如果可以,方案B+C组合是最佳选择。如果不行,需要方案A(hair_service_sd 按需启停)+ 方案C + swapHair 异步化。
需要你确认:
- 接口2女是否可以去掉 swapHair(直接用原图+遮罩 → ComfyUI)?
- 是否可以永久停止 SD WebUI 和 hair_service_sd?
- steps 从 6 降到 2 是否可接受(需要质量验证)?