agentscope-ai / agentscope-ai/QwenPaw
[Performance] MCP drivers start sequentially instead of in parallel
- 主要言語
- Python
- スター
- 34.9k
- フォーク
- 3.1k
- 平均マージ
- 1日 15時間
- マージ済み PR(30日)
- 225
説明
## 背景
QwenPaw 启动时,MCP 驱动(Driver handlers)是串行逐个初始化的。
配置 8 个 MCP 客户端时,光等 MCP 连接就要花 ~40 秒;改成并行初始化后,同样的 8 个客户端只需 ~5 秒,快 8 倍。
## 问题定位
文件:`src/qwenpaw/drivers/manager.py`
`build_drivers()` 方法用 `for` 循环逐个 `await`,每个 MCP 连上了才开始下一个:
```python
async def build_drivers(self) -> None:
for path in await self._card_store.list_paths():
...
handler = await self._build_and_init_handler(card)
built[card.name] = handler
```
每个 `_build_and_init_handler()` 会拉起一个子进程(如 `npx tavily-mcp`),等它连接成功后,才继续下一个。
有趣的是,关闭流程(`_shutdown_handlers`)已经用了 `asyncio.gather()` 做并行——但启动流程没有。
## 实测数据
环境:QwenPaw 2.0.0.post2 / Windows 10 / 8 个 MCP 客户端。从 `qwenpaw.log` 测量:
| 阶段 | 耗时 |
|---|---|
| 第一个 MCP 开始 | 0s |
| 最后一个 MCP 连接完成 | 41s |
| 后端总启动 | 143s |
8 个串行 × 每个 ~5s = 41s → 并行后取最慢的一个 ≈ 5s。
## 建议修复
把 `for` 循环替换为 `asyncio.gather()`,保留原有错误处理(失败的跳过,不致命):
```python
async def build_drivers(self) -> None:
cards = []
for path in await self._card_store.list_paths():
try:
card = await self._card_store.load_path(path)
except Exception as exc:
logger.warning("Failed to load Driver card: %s", exc, exc_info=True)
continue
if not card.enabled:
continue
cards.append(card)
results = await asyncio.gather(
*[self._build_and_init_handler(card) for card in cards],
return_exceptions=True,
)
built = {}
for card, result in zip(cards, results):
if isinstance(result, Exception):
logger.warning("Failed to build Driver: %s", result, exc_info=True)
else:
built[card.name] = result
async with self._lock:
old = self._handlers
self._handlers = built
await self._shutdown_handlers(old.values())
```
## 相关
- 关闭流程已并行化:`_shutdown_handlers()` 使用 `asyncio.gather()`
- #4834(MCP 进程累积)— 已由 PR #5014 修复
- #5047(桌面端启动慢)— Tauri 相关,但后端优化也有帮助
如果团队认可,我可以直接提 PR。
コントリビューションガイド
評価
この issue はまだ評価されていません。