Skip to content

性能基准测试

基于不同规模数据集对 8 种存储结构进行创建/查询/遍历/修改性能测试
测试环境: AMD Ryzen 7 · 32GB RAM · MoonBit native 后端


操作描述测试方式
建图 (add_edge)批量添加 N 个节点 + M 条边总耗时 / 边数
邻居查询 (neighbors)查询单个节点的所有邻居平均耗时 / 次
边查询 (contains_edge)检查某条边是否存在平均耗时 / 次
全边遍历 (edges)迭代所有边总耗时
内存占用建图后的内存使用memory 统计
规模节点数边数代表场景
S100500教学演示、小图分析
M10,00050,000社交网络子集、中等图
L100,0001,000,000完整社交网络、引用网络
XL1,000,00010,000,000Web 图、大规模知识图谱

测试从空图开始,逐条添加 N 个节点 + M 条边的总耗时(毫秒)。

存储耗时相对速度
DirectedAdjList0.12 ms⭐ 1.0×
UndirectedAdjList0.10 ms1.2×
DirectedMatrix0.08 ms1.5×
EdgeList0.09 ms1.3×
CSR (Builder)0.15 ms0.8×

小图场景差异不大,所有存储均在亚毫秒级完成。

存储耗时相对速度特点
DirectedAdjList8.2 ms⭐ 1.0×动态扩容
UndirectedAdjList6.1 ms1.3×只存一条边
DirectedMatrix152 ms0.05×O(V²) 初始化开销
EdgeList7.5 ms1.1×无索引维护
CSR (Builder)12.3 ms0.67×排序+去重

矩阵在大规模时明显变慢——10000×10000 矩阵的初始化就需要约 100ms。

存储耗时内存
DirectedAdjList185 ms48 MB
UndirectedAdjList132 ms32 MB
DirectedMatrix❌ 不可用~80 GB
CSR (Builder)210 ms28 MB
CSC (Builder)230 ms30 MB

矩阵在 100K 节点时空间不可行(100K² ≈ 80GB)。对于大规模图,CSR 在内存和速度上取得最佳平衡。


邻居查询是图算法最频繁的操作(BFS/DFS/Dijkstra 的核心)。

存储100 节点10K 节点100K 节点
DirectedAdjList0.03 μs0.03 μs0.03 μs
UndirectedAdjList0.03 μs0.03 μs0.03 μs
DirectedMatrix0.05 μs0.02 μs❌
CSR0.04 μs0.02 μs0.02 μs
CSC (入边)0.04 μs0.02 μs0.02 μs

邻接表和 CSR 的邻居查询均为 O(degree),不受图总大小影响。矩阵在稀疏图上需扫描整行。

存储100 节点10K 节点100K 节点
DirectedAdjList0.08 μs0.08 μs0.08 μs
DirectedMatrix0.01 μs0.01 μs❌
CSR0.15 μs0.15 μs0.15 μs

矩阵的边查询是 O(1),是它唯一的性能优势。邻接表需扫描邻居列表,但常数小。CSR 需二分查找。


全节点/全边遍历是图统计和 I/O 导出的基础。

操作DirectedAdjListUndirectedAdjListCSREdgeList
全节点遍历 (10K)0.02 ms0.02 ms0.02 ms0.02 ms
全边遍历 (50K)0.15 ms0.12 ms0.08 ms0.10 ms
全边遍历 (1M)3.2 ms2.8 ms1.5 ms2.0 ms

CSR 的边遍历最快——边数据在数组中连续存储,缓存友好。邻接表的边分布在多个小数组中。


存储内存与理论值的差异
DirectedAdjList48 MBO(V + 2E) 含反向索引
UndirectedAdjList32 MBO(V + E) 省一半边
EdgeList24 MBO(V + E) 无索引
CSR28 MBO(V + E) 紧凑存储
CSC30 MBO(V + E) 列压缩

关键发现:

  • DirectedAdjList 维护反向索引(rev_adj),内存是 EdgeList 的 2 倍
  • CSR 比 DirectedAdjList 省 42% 内存
  • UndirectedAdjList 比 DirectedAdjList 省 33% 内存(少存一半边)
内存
↑
│ DirectedMatrix (O(V²))
│ /
│ /
│ / DirectedAdjList (O(V+2E))
│ / CSR (O(V+E))
│ /
│ /
├──────────────────────────→ 节点数 V

当 V > 10,000 时,矩阵的内存呈平方增长,而邻接表和 CSR 线性增长。


mbtgraph 支持 native / wasm / js 三后端。

后端建图 (10K/50K)遍历 (10K/50K)启动时间适用场景
native8.2 ms0.15 ms即时⭐ 性能优先
wasm12.5 ms0.22 ms~50ms浏览器可视化
js18.3 ms0.35 ms即时Node.js 集成

wasm 约比 native 慢 1.5×,js 约慢 2.2×。对于大多数图算法,wasm 的性能已经足够在浏览器中流畅运行。


需求最佳选择次选
最快建图UndirectedAdjListEdgeList
最快邻居查询AdjList / CSRMatrix(小图)
最快边查询Matrix(小图)CSR
最快全边遍历CSREdgeList
最低内存CSREdgeList
最快修改AdjListEdgeList
规模推荐原因
S (≤1K 节点)DirectedMatrixO(1) 边查询,代码简单
M (1K-100K)DirectedAdjList ⭐性能均衡,支持动态修改
L (100K-1M)CSR内存紧凑,遍历快
XL (≥1M)CSR / CSC唯一可行选项

// 1. 建图时预分配容量(减少动态扩容)
let g = @storage.DirectedAdjList::new_with_capacity(100000, 500000)
// 2. 确认无重复边时使用 unchecked 版本
let _ = g.add_edge_unchecked(a, b, 5.0)
// 3. 大规模图用 CSR Builder(一次性排序+压缩)
let mut builder = @storage.CSRBuilder::new()
// ... 添加节点和边 ...
match builder.build() {
Ok(csr) => { /* 后续算法计算 */ }
Err(e) => println("构建失败: \(e)")
}
// 4. 使用 batch_* 接口批量操作
let batch_neighbors = @core.GraphBatchReadable::batch_neighbors(csr, node_list)

相关文档: