# 性能优化指南

本文档详细介绍 Code Search MCP 的性能特性和优化策略。

## 性能指标

### 索引性能

| 场景 | 首次索引 | 增量索引 | 备注 |
|------|----------|----------|------|
| 10 文件 | < 0.1s | < 0.05s | 极快 |
| 100 文件 | < 1s | < 0.1s | 快速 |
| 1000 文件 | < 10s | < 1s | 中等 |
| 10000 文件 | < 2min | < 10s | 需优化 |

### 搜索性能

| 操作 | 平均延迟 | P99 延迟 |
|------|----------|----------|
| find_files | 5ms | 10ms |
| find_symbols | 8ms | 15ms |
| find_content | 10ms | 20ms |
| get_structure | 3ms | 8ms |

### 资源占用

| 指标 | 数值 |
|------|------|
| 内存占用 | < 50MB |
| 磁盘占用 | ~1MB/1000 文件 |
| 启动时间 | < 500ms |

---

## 增量索引

### 工作原理

Code Search 使用文件修改时间戳判断是否需要重新索引：

```
1. 扫描文件系统
2. 对比文件 modified_time vs indexed_at
3. 仅索引变更文件
4. 自动清理删除的文件
```

### 性能对比

| 模式 | 100 文件 | 1000 文件 | 10000 文件 |
|------|----------|-----------|-------------|
| 全量 (force_rebuild=True) | 0.8s | 8s | 80s |
| 增量 (force_rebuild=False) | 0.05s | 0.5s | 5s |
| 提升 | 16x | 16x | 16x |

### 最佳实践

```python
# ✅ 推荐：始终使用增量索引
index_repository: {
    "repo_path": "/path/to/repo",
    "force_rebuild": False  # 关键！
}

# 仅在以下情况使用全量：
# - 首次索引
# - 索引损坏
# - 重大代码重构后
```

---

## 搜索优化

### 1. 使用扩展名过滤

```python
# ✅ 快速：限定文件类型
find_files: {
    "query": "test",
    "extensions": [".py"]
}

# ❌ 较慢：扫描所有文件
find_files: {
    "query": "test"
}
```

### 2. 使用文件模式过滤

```python
# ✅ 快速：限定目录
find_content: {
    "query": "TODO",
    "file_pattern": "**/src/**/*.ts"
}

# 避免：全项目搜索
find_content: {
    "query": "TODO"
}
```

### 3. 合理设置 limit

```python
# ✅ 平衡：足够定位即可
find_files: {"query": "x", "limit": 20}

# ⚠️ 过多：增加传输负担
find_files: {"query": "x", "limit": 1000}
```

### 4. 使用正则的代价

| 模式 | 延迟 |
|------|------|
| 普通搜索 | 5ms |
| 正则搜索 | 10ms |
| 复杂正则 | 20ms+ |

建议：
```python
# ✅ 优先使用普通搜索
find_content: {"query": "function"}

# ⚠️ 正则仅在必要时使用
find_content: {"query": "^def\\s+", "regex": True}
```

---

## 并行处理

### 多搜索并行

```python
import asyncio

# 并行执行多个搜索
results = await asyncio.gather(
    session.call_tool("find_files", {"query": "test"}),
    session.call_tool("find_symbols", {"query": "class"}),
    session.call_tool("find_content", {"query": "TODO"}),
    session.call_tool("get_stats", {})
)

# 总时间 ≈ 最慢单个请求
# 串行时间 = sum(各请求时间)
```

### 搜索链优化

```python
# ❌ 串行：浪费等待时间
files = find_files({"query": "x"})
structure = get_structure({"file": files[0]})

# ✅ 找到目标后立即获取结构
files = find_files({"query": "x"})
if files:
    structure = get_structure({"file": files[0]["path"]})
```

---

## 内存管理

### 日志缓冲

Code Search 维护内存缓冲存储最近日志：

```python
# 默认缓冲 1000 条
# 可通过 memory_limit 参数调整

# 创建小缓冲
logger = Logger(path, memory_limit=100)
```

### 清理旧日志

```python
# 清理 7 天前的日志
logger.clear_old_logs(days=7)

# 清理所有日志
logger.clear_old_logs(days=0)
```

---

## 性能监控

### 获取统计

```python
# 索引统计
get_stats: {}

# 调用统计
get_call_stats: {}

# 返回示例：
{
    "call_stats": {
        "total_calls": 500,
        "avg_duration_ms": 12.5,
        "by_tool": [
            {"tool_name": "find_files", "count": 200, "avg_duration": 5.2},
            {"tool_name": "find_content", "count": 150, "avg_duration": 10.1}
        ]
    }
}
```

### 慢查询识别

```python
# 查看最近的慢查询
get_logs: {"limit": 20}

# 筛选慢调用（> 100ms）
# 日志中 level=WARNING 表示 > 5s
```

---

## 最佳实践总结

### 索引

1. **始终使用增量索引**
2. **首次索引后可定期更新**
3. **大规模仓库考虑分批索引**

### 搜索

1. **使用扩展名/文件模式过滤**
2. **合理设置 limit**
3. **避免不必要的正则搜索**
4. **并行化多个独立搜索**

### 监控

1. **定期检查 get_call_stats**
2. **清理旧日志**
3. **关注慢查询**

---

## 性能问题排查

### 问题：索引变慢

**可能原因：**
1. 文件系统变慢（网络存储）
2. 大量小文件
3. 编码问题

**排查：**
```python
# 检查日志
get_logs: {"success": False}

# 检查文件数量
get_stats: {}
```

### 问题：搜索变慢

**可能原因：**
1. 数据量过大（>10万文件）
2. 没有使用过滤
3. 复杂正则

**优化：**
```python
# 添加过滤
find_content: {"query": "x", "file_pattern": "**/src/**"}

# 简化正则
find_content: {"query": "simple", "regex": False}
```
