Midscene.js 自动化脚本卡顿怎么排查?从诊断到提速的实战指南
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
Midscene.js 是一个 AI 驱动的 GUI 自动化工具,你用一句自然语言就能让 AI 替你点按钮、填表单、读页面,常用于端到端测试和重复性操作。它的性能开销主要集中在"截图 → 发给视觉模型 → 解读结果"这条链路上,任何一环变慢,整个脚本都会跟着卡。这篇文章先教你用可观察的数据判断卡顿出在哪,再按瓶颈逐个给出调参和配置方案,读完你能独立定位大多数"跑得慢"的问题。
🩺 快速自检:Midscene.js 性能问题怎么判断
动手改参数之前,先确认两件事:是不是真的有性能问题、问题出在哪一段。看四个可以直接观察到的信号就够了:
- 每步耗时:每次运行结束后,报告的左侧栏会列出 Planning、Locate、Action 等每一步的耗时。某一步稳定超过 10 秒,就是第一个该怀疑的点。
- 重规划次数:日志里如果出现 "Replanned N times",说明模型第一次没把指令拆成可执行步骤,一直在返工。
- 两次总耗时对比:同一个脚本第二遍跑下来的总耗时和第一遍一样,说明缓存没生效,AI 调用全价重付了一遍。
- 内存曲线:每一步都会把整张截图编码后传给模型,长脚本里 Node 进程内存持续上涨是正常但需要留意的现象。
一句话经验:只有单步慢,多半是模型调用或指令太复杂;每步都慢,多半是网络或模型服务的问题;第二遍不比第一遍快,就是缓存没工作。下面按这四类瓶颈分别展开。
🔍 单步耗时过长:模型调用慢怎么优化
症状:某一个 Planning 或 Locate 步骤要 10 秒以上,脚本大部分时间停在原地等结果。
根因:视觉模型每次都要读完整张截图,再输出一份结构化结果。页面元素越多、指令越含糊,它花的越久。这类似让一个人"看一眼就把所有事办完",线索越少他越磨蹭。
对策:
- 指令写短、写具体。把"找到列表里第一个耳机、确认它的价格、再点进详情页"拆成三条短句,而不是一句长指令。
- 按任务难度选模型家族:复杂页面交给强模型,简单确认类步骤交给轻量模型,用环境变量
MIDSCENE_MODEL_FAMILY切换。 - 给慢的环节单独设超时(
MIDSCENE_PLANNING_MODEL_TIMEOUT、MIDSCENE_MODEL_TIMEOUT),避免一次慢调用把整条流程拖死。
指令拆细之后,返工的重规划会明显减少。但如果任务确实复杂,重试本身也会消耗时间,所以下一节处理重试。
🔁 反复重试卡住:replanning 次数如何设置
症状:日志连续打出 "Replanned N times, exceeding the limit",脚本停在同一步不再前进。
根因:复杂指令在单次规划里拆不出来时,Midscene.js 会反复重规划,而每一轮重规划都是一次完整的模型调用。重试越多,"慢"就越多,还叠加了失败风险。
对策:
- 首选还是把长指令拆小,每条指令只描述一个明确动作,这是治本的办法。
- 任务本身步骤多时,把重规划上限从默认值调大:用配置项
replanningCycleLimit,或批量运行时用环境变量统一控制:
export MIDSCENE_REPLANNING_CYCLE_LIMIT=5 export MIDSCENE_PLANNING_MODEL_TIMEOUT=90000- 注意:上限只是缓冲垫。如果长期贴着上限才通过,说明指令还是写得太大,调大上限是在替含糊的指令买单。
重试解决的是"做不好"的问题,还有一类更安静的时间花在了"重复做已经做过的活"上——这就是缓存。
📦 重复执行总是等满全程:缓存没命中怎么配
症状:同一个脚本连跑两遍,第二遍的总耗时和第一遍几乎一样。
根因:每个 Locate、Planning 步骤都是一次独立的 AI 调用。Midscene.js 内置了任务缓存(实现见 task-cache.ts),同一个缓存 id 的结果下次可以直接读取,不再调用模型。不开启的话,每次运行都在全额付费。
对策:给 AI 调用配置缓存对象,关键是 id 和 mode 两个字段:
cache: { id: 'ebay-search-flow', // 同一脚本用同一个 id mode: 'read-write', // 首跑写入,后续直接读取 }- id 起有业务含义的名字,不要多个脚本共用 'default',否则互相污染。
- 页面改版后要先清掉旧缓存再重新写入,否则脚本会照着旧坐标操作。
- 旧写法是
cacheId加MIDSCENE_CACHE=1环境变量,新代码建议直接用上面对象写法。
缓存解决的是重复劳动,还有一类慢是"活本身太重"——每一步都要搬一张大截图。
🖼️ 截图又大又重:图像处理开销怎么降
症状:同一脚本在高解析率屏幕或 Retina 设备上跑,比低分屏明显慢,且慢得稳定。
根因:每一步都会把截图编码成 base64 传给视觉模型,图越大,编码和传输越久。Midscene.js 的图像处理模块(transform.ts)默认以 JPEG 质量 90 编码,文字密集的页面会留下不少冗余体积。
对策:
- 先看耗时是否随页面像素量线性上涨,是的话瓶颈就在图片体积。
- 对不需要像素级还原的场景,把编码质量
jpegQuality降到 80 左右,肉眼几乎无差别,体积明显下降。 - 视口不要开大:能放进 1280×720 完成验证的页面,没必要用 1920×1080。
图变小了、缓存也有了,如果脚本还是"莫名其妙卡住",多半是你根本没看到它卡在哪。
🐛 脚本莫名挂起:调试与日志怎么开
症状:脚本停在某一步不动,没有报错,分不清是模型慢、网络断还是页面没加载。
根因:默认日志只输出概要信息,模型调用内部是黑盒,出问题后手里没有任何证据可查。
对策:打开调试模式,把细节全部落到日志里:
export MIDSCENE_DEBUG_MODE=1 export MIDSCENE_DEBUG_LOG_JSON=1- 前者打开调试模式,后者输出结构化的 JSON 日志,方便接终端或日志系统聚合分析。
- 定位性能时,把报告里的每步耗时和日志时间戳对一遍,就能看出时间到底花在模型调用上还是页面操作上。
诊断手段齐了,把上面各节涉及的参数汇总成一张表,方便对照着调。
⚙️ 关键参数速查表
| 参数 | 作用 | 推荐值 | 适用场景 |
|---|---|---|---|
cache.id | 缓存标识,相同 id 复用已有结果 | 有业务含义的稳定字符串 | 回归中反复运行的同一脚本 |
cache.mode | 缓存读写模式(read / write / read-write) | read-write | 首跑写入、后续读取 |
MIDSCENE_CACHE=1 | 旧版缓存总开关 | 1 | 兼容cacheId旧配置 |
replanningCycleLimit | 重规划重试次数上限 | 3~5 | 步骤多的复杂任务 |
MIDSCENE_REPLANNING_CYCLE_LIMIT | 环境变量形式的重试上限 | 与上一项保持一致 | CI 批量运行统一控制 |
MIDSCENE_MODEL_TIMEOUT | 模型调用总超时(毫秒) | 120000 | 网络不稳时防止无限挂起 |
MIDSCENE_PLANNING_MODEL_TIMEOUT | 规划类调用单独超时(毫秒) | 90000 | 规划步骤明显偏慢时 |
MIDSCENE_INSIGHT_MODEL_TIMEOUT | 洞察类调用单独超时(毫秒) | 按实测耗时上浮 | 页面信息提取耗时波动大 |
MIDSCENE_MODEL_FAMILY | 模型家族选择 | 按任务复杂度选 | 轻量与强模型混用 |
jpegQuality | 截图编码质量,默认 90 | 80~90 | 带宽敏感、图片体积敏感 |
MIDSCENE_DEBUG_MODE | 调试模式开关 | 1 | 排查卡顿与挂起 |
MIDSCENE_DEBUG_LOG_JSON | JSON 结构化详细日志 | 按需 | 自动化采集日志 |
📈 实战案例:电商搜索脚本从 7.36 秒到 0.94 秒
场景是一条 Playwright + Midscene.js 的冒烟脚本:打开电商首页,搜索 headphones,确认第一条商品的名称和价格。它每天要在流水线里跑二十次以上。
优化前:每次运行总耗时约 7.36 秒,其中四个 Planning / Locate 步骤各占 3~7 秒,全部是模型调用开销;连续跑二十次,总时间一秒没省,模型账单照付。
做了三处调整:
- 给每个 AI 步骤配置了稳定的缓存 id,mode 设为 read-write,首跑写入、后续读取。
- 把一条超长指令拆成两条短指令,重规划次数归零。
- 在 CI 里对回归流水线单独配了只读缓存,生产侧不再触发任何写入。
优化后:缓存命中时同样流程的总耗时降到 0.94 秒,缩减约 87%。即使偶尔缓存失效走全量冷跑,也只回落到原来的 7 秒出头,日常二十次冒烟的总体耗时和模型调用量都大幅下降。
⚠️ 常见误区
- 很多人开启缓存后就放任不管 → 页面改版后脚本照旧坐标操作,报错又碎又难查 → 正确做法:消费端用只读模式,页面变更时主动清缓存并重新写入。
- 很多人把一整套流程塞进一条大指令,以为能省步骤 → 指令越复杂,规划失败和重规划越多,重试花的时间远超省下的时间 → 正确做法:一条指令只做一个动作,重复的部分交给缓存。
- 很多人把模型超时调得很小,想"快速失败" → 正常的慢调用也被掐断,脚本时好时坏 → 正确做法:先在报告里看真实步骤耗时,再把阈值设在实际值之上。
- 很多人为省事给所有脚本用同一个缓存 id → 不同脚本读到彼此的结果,问题偶发且难以复现 → 正确做法:id 里带上业务名和场景名,一脚本一 id。
收尾
提速的核心就两条:已经付过钱的模型调用不重复做,做不好的大任务拆成模型一次能做的。先打开报告看每步耗时,确认时间花在哪一段,再对着参数表调,能避开绝大多数盲目试错。缓存与模型的完整配置说明,可以看仓库里的 缓存文档和模型配置文档。
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考