agentscope-ai / agentscope-ai/QwenPaw

[Performance] MCP drivers start sequentially instead of in parallel

オープン
#6,193 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
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 はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。