背景
很多人第一次排查 OpenTAP 的资源问题时,会默认“计划一启动就把所有 Instrument 全部 Open”。但真实行为更细:资源何时打开,取决于当前执行阶段(Open / Execute / PrePlanRun / Run / PostPlanRun)以及资源是否已进入打开任务队列。这个差异直接影响启动耗时、失败暴露时机和日志观感。
框架分析
核心在 Engine/ResourceTaskManager.cs 的 BeginStep(...)。它不是单一入口做同一件事,而是按 TestPlanExecutionStage 分支:
Execute:若存在空资源引用,先触发一次BeginOpenResources,再启动StartResourcePromptAsync;提示之后如果仍有未建任务资源,再补一次打开。Open:对整计划静态资源与启用步骤资源做集中打开。PrePlanRun/Run:不会盲目再开,而是检查已有openTasks是否全部RanToCompletion;若未完成,才阻塞等待WaitUntilAllResourcesOpened。PostPlanRun:不新增打开动作。
这说明 OpenTAP 的策略不是“全量预热”,而是“阶段感知 + 必要时等待”。
实现过程
可复现命令(直接定位门控逻辑):
1 | cd /home/ops/clawd/repos/opentap |
本地阅读时重点盯三件事:openTasks 的填充时机、resources.Any(...) 的两次判定、以及 Execute 分支里“先处理空引用再弹资源提示”的顺序。把这三点串起来,就能解释为何有些计划在启动时快、但在进入 PrePlanRun 前会短暂停顿。
注意事项
PrePlanRun/Run阶段的等待是“条件等待”,不是固定阻塞;日志里偶发等待通常意味着前序打开任务仍在跑或曾失败。- 资源提示 (
StartResourcePromptAsync) 与打开流程交错存在,插件里不要假设提示完成就代表资源一定已全部可用。 - 若自定义资源存在依赖链,建议结合
ResourceOpenAttribute明确依赖打开语义,避免在阶段切换点出现“看似随机”的等待抖动。
小结
BeginStep 的价值在于把资源管理从“单次动作”改成“阶段门控流程”:该并发时并发、该提示时提示、该等待时再等待。理解这套门控后,排查“为什么不是一开始就全开”或“为何在 PrePlanRun 前卡一下”会快很多。
关键源码路径:
Engine/ResourceTaskManager.cs(TestPlanExecutionStage、BeginStep、BeginOpenResources、WaitUntilAllResourcesOpened)Engine/TestPlan.cs(测试计划执行阶段与资源管理协作入口)Engine/ILockable.cs(资源打开前后锁管理扩展点)