Files
cs-note/hhs/GIN/2-routing/2-routing-complexity-comparison.md
T
2026-05-24 11:42:38 +08:00

81 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [后端, Go, Gin, 路由, 性能]
create time: 2026-04-27 00:00
---
# 路由匹配复杂度对比:Gin vs http.ServeMux
## 概述
对比 Gin 的 Radix Tree 路由匹配与 Go 标准库 `http.ServeMux` 的匹配机制,从数据结构、算法复杂度到实际性能差异进行全面分析。
## 正文
### 1. ServeMux 的匹配机制
`http.ServeMux` 内部维护一个 `map[string]pattern` 映射,匹配一个 URL 时需要:
1. **遍历所有已注册的路由**(按最长前缀匹配规则)
2. 对每条路由做一次**完整的路径字符串比较**
3. 时间复杂度 **O(R × L)**,其中 **R = 路由总数**,**L = URL 长度**
> 补充细节:`ServeMux` 支持两种匹配模式:前缀匹配(`/prefix/`)和精确匹配。前缀匹配需要从所有可能的前缀中筛选出最长的候选者,因此会遍历多个条目,而不是 O(1) 的哈希查找。
### 2. Gin Radix Tree 的匹配机制
Gin 的路由组织为一棵压缩前缀树(Radix Tree),匹配过程:
1. 从根节点开始,沿着 URL 的字符**逐段向下走**
2. 每段匹配利用前缀共享,一次比较就决定走向
3. 时间复杂度 **O(D)**,其中 **D = URL 深度(路径段数)**,通常只有 3-5 层
> 与路由总数 **R 无关**。10 条路由和 10000 条路由,匹配 `/api/v1/users/5` 的步数几乎一样。
### 3. 具体差距
| 场景 | ServeMux | Gin (Radix Tree) |
|------|----------|-----------------|
| 10 条路由 | ~10 次完整比较 | ~4 步 |
| 100 条路由 | ~100 次 | ~4 步 |
| 1000 条路由 | ~1000 次 | ~4 步 |
| 10000 条路由 | ~10000 次 | ~4 步 |
**数量级差异**:当路由数增长时,ServeMux 线性增长,Gin 基本保持不变。在路由较多的场景下,Gin 的匹配速度通常是 ServeMux 的 **10~100 倍甚至更多**。
### 4. 根本原因:数据结构差异
- **ServeMux 用的是哈希表**:`map[string]Handler` 虽然对精确匹配是 O(1),但 HTTP 路由还需要处理前缀匹配(`/api/...`),这退化为遍历比较。哈希表丢失了"路径前缀"的结构信息。
- **Gin 用的是 Radix Tree**:天然保留路径前缀结构,匹配时走树不走表,每一步都能利用前缀信息直接跳到下一段,不需要回溯或比较无关路由。
**一句话总结**:ServeMux 是在一叠卡片里逐张翻,Gin 是在字典里按部首和拼音直接定位。
### 5. 可视化对比
```mermaid
flowchart TD
subgraph S ["ServeMux:遍历比较"]
S1["遍历路由 #1: /users/list"] --> S2["遍历路由 #2: /users/:id"]
S2 --> S3["遍历路由 #3: /users/*path"]
S3 --> S4["..."]
S4 --> S5["遍历路由 #N"]
end
subgraph G ["Radix Tree:树形定位"]
G1["根节点 /"] --> G2["users"]
G2 --> G3{下一步?}
G3 -->|"list"| G4["list ✓"]
G3 -->|"数字"| G5[":id ✓"]
G3 -->|"其他"| G6["*path ✓"]
end
classDef S fill:#ffebee,stroke:#c62828
classDef G fill:#e8f5e9,stroke:#2e7d32
class S,S1,S2,S3,S4,S5 S
class G,G1,G2,G3,G4,G5,G6 G
```
## 关联笔记
- `[[2-routing]]` — Gin 路由匹配与分组机制