You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

图单数组邻接存储与常规邻接表10倍性能差异原因求解

两种图实现性能差距的核心原因

两种实现的性能差距主要来自内存布局、装箱开销、分配开销三个层面的叠加,具体如下:

  • 缓存友好性差距
    Graph1的所有邻接节点都存储在单个连续的原生int数组edgeEndpoints中,内存地址完全连续,CPU的缓存预取机制可以大幅提升访问命中率,即使写入阶段有随机访问,所有操作也都落在同一块连续内存区域,缓存行利用率极高。
    而Graph2的邻接表是ArrayList<Integer>[]结构,每个ArrayList是独立的堆对象,其内部存储数据的数组也分散在堆内存的不同位置,访问不同节点的邻接表时需要跳转不同的内存地址,缓存miss率远高于连续数组实现,在百万级节点的场景下差距会被放大。
  • 原生类型与装箱的开销差距
    Graph1全程使用int原生类型存储节点编号,无任何装箱拆箱操作。
    而ArrayList只能存储对象类型,每次add整数、访问整数时都需要做int和Integer的自动装箱拆箱,单条操作开销虽然小,但800万次(400万条无向边对应两次add)的累计开销非常可观。
  • 内存分配与扩容开销差距
    Graph1仅需要一次性分配3个固定大小的原生数组:edgeEndpoints(长度2*M)、l和r(各长度N),分配次数极少,无额外内存开销。
    而Graph2需要创建N个ArrayList对象,每个ArrayList默认初始容量为10,如果节点度数超过10就会触发扩容:扩容需要重新分配更大的数组、复制原有数据,大量扩容操作会带来极高的额外开销。同时100万个ArrayList对象本身的对象头、元数据也会带来额外的内存占用和访问开销。

内容的提问来源于stack exchange,提问作者Will Kanga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 13:36:02