顶点遍历三种实现方案性能对比:直接数组vs间接对象访问
核心结论
三种方案存在明显性能差异,差异根源在于内存缓存友好性和间接访问的指令/缓存开销。
各方案性能对比
方案1(全局顶点数组+单独网格ID数组)
这是三者中性能最优的方案。所有顶点存储在连续内存块中,CPU的缓存预取机制可以批量加载后续顶点,缓存命中率极高;同时mesh_ids数组也是连续内存,访问模式和顶点数组完全匹配,进一步提升缓存效率。唯一的额外成本是维护mesh_ids数组,但遍历阶段的开销可以忽略。方案2(每个网格维护独立顶点数组)
性能略逊于方案1。单个网格内的顶点是连续内存,缓存友好,但不同网格的顶点数组在内存中通常是分散的。切换网格时,CPU缓存会失效,需要重新加载新的内存块,缓存命中率下降。不过该方案没有指针间接访问,仅通过数组索引遍历,所以比方案3高效。方案3(Model持有Mesh指针,两层嵌套遍历)
性能是三者中最差的。存在两层指针间接访问:先读取models[i].mesh指针,再通过该指针访问Mesh的顶点数组。每次指针解引用都可能触发缓存 miss(如果指针本身不在缓存中),同时会增加CPU的指令执行次数。此外,Model包含的非网格数据会占用缓存空间,挤压顶点数据的缓存位置,进一步降低遍历效率。
关键问题解答
直接访问数组是否比中间对象访问有性能优势?
是的。直接数组访问是连续内存的索引操作,CPU可以精准预测访问模式,提前预加载数据到缓存,大幅减少缓存 miss;而中间对象(如方案2的meshes[i]、方案3的models[i].mesh)对应的内存块通常是分散的,或者需要额外的指针解引用,会增加缓存失效的概率和指令开销。Model+Mesh两层间接访问是否存在性能损耗?
确实存在。一是指针解引用的开销:两层间接需要两次内存读取操作,每一步都可能触发缓存 miss;二是缓存资源挤占:Model的非网格数据会占用L1/L2缓存的有限空间,导致顶点和Mesh相关数据更难留在缓存中,放大缓存 miss的影响。
内容的提问来源于stack exchange,提问作者Chris Gnam

