在程序员的必修课清单里,有一堂快十年前留下的演讲,至今仍被反复引用:Mike Acton 在 CppCon 2014 上的《Data-Oriented Design and C++》。它不是一堂 C++ 语法课,而是一次对默认编程习惯的公开审判——你以为性能问题是算法问题、语言问题、编译器问题,Acton 说:都不是,是你摆数据的方式出了问题。这堂课的价值在于,它把“计算机体系结构”课本里躺着的那几页缓存知识,直接怼到了每一个写过 class、new 和指针的人面前。本文带你完整吸收这堂课的论证结构,并补充它背后的真实研究脉络与十年来被验证、被修正的部分。没看过视频也能读懂,看过视频的人会多懂一层。
| 项目 | 内容 |
|---|---|
| 视频标题 | Data-Oriented Design and C++(数据导向设计与 C++) |
| 频道 | CppCon(C++ 大会官方频道) |
| 主讲人 | Mike Acton,时任 Insomniac Games 技术总监(代表作《瑞奇与叮当》系列),此后加入 Unity |
| 发布时间 | CppCon 2014 大会演讲(2014 年 9 月,美国贝尔维尤),会后上传至官方频道 |
| 时长 | 约 1 小时 |
| 热度 | 据频道页面,播放量为百万级,是 CppConv 历史上被引用、被讨论最多的演讲之一 |
这堂课最出名的不是某个技巧,而是 Acton 的开场姿态。他几乎是在挑衅台下:你们大多数人根本不知道自己的硬件每秒钟在干什么。CPU 的主频、缓存的层级、内存的延迟、总线的带宽——这些参数写在每一个规格表上,但绝大多数程序员写代码时假装它们不存在。
他的原话大意是:“硬件不是你的朋友。”这不是说硬件不可靠,而是说硬件的优化逻辑和程序员的直觉完全相反。程序员直觉里,代码是顺序执行的、内存是均匀的、访问任何一个变量的代价差不多。而真实硬件上,一次内存访问和一次缓存命中的代价可以差上百倍。Acton 的第一个论点由此立住:写高效程序的前提,是先承认硬件的真实脾气,而不是活在抽象的幻觉里。
这里值得补一层视频里没有展开的数字感:一颗 3GHz 的 CPU,一个时钟周期约 0.3 纳秒;而一次主存访问通常是几十到上百纳秒。也就是说,缓存未命中一次,CPU 要空等几百个周期。这个量级差距,就是整堂课所有论证的物理基础。
Acton 抛出的第二击,是对“软件是什么”的重新定义:软件就是对数据的变换(transformation of data)。你写的每一行代码,本质上都在描述“输入数据如何变成输出数据”。因此,设计程序的起点不应该是对象、类、设计模式,而应该是数据本身。
他给出了四个必须在动手前回答的问题,这也是整堂课最实用的框架:
这四个问题决定了一件事:数据在内存里应该怎么摆。Acton 认为,绝大多数性能问题的根子,就是程序员从来没回答过这四个问题,直接从“我要建哪几个类”开始写代码。
接下来是全课的核心技术段:缓存行(cache line)。现代 CPU 和内存之间隔着 L1、L2、L3 三级缓存,数据搬运的最小单位不是字节,而是一整个缓存行——x86 上是 64 字节。哪怕你只想读结构体里的一个浮点数,硬件也会把周围整整 64 字节拖进缓存。
这个设计的赌注是“局部性”:如果你接下来要用的是旁边的数据,缓存就赚了。这里补一层背景:局部性原理是有正式学术出处的——Peter Denning 在 1968 年建立的局部性模型,是虚拟内存和缓存体系的理论地基;1995 年 Wulf 和 McKee 的著名论文《Hitting the Memory Wall》更是直接警告:CPU 越来越快而内存越来越跟不上的“内存墙”,将成为体系结构的核心矛盾。三十年过去,这堵墙非但没有消失,反而更高了。
Acton 用一个经典演示把抽象道理变成体感:屏幕上大量粒子各自带有位置、速度、颜色、名字等一堆字段,每帧更新时你其实只用其中两三个字段。如果把对象一个挨一个存(面向对象的自然写法,业界称为 AOS),硬件每次都要为两个浮点数拖回 64 字节,其中大半是当帧完全用不上的颜色和名字;如果反过来按字段拆开、把所有位置连续存放、所有速度连续存放(AOS 改 SOA),一行缓存里全是有效数据,缓存命中率暴增,硬件预取器还能顺着连续地址提前把数据喂进缓存。两种写法在演示机上的差距是数倍——而算法一行都没改。
顺带多懂一层:缓存行至今仍是硬件厂商的博弈点。x86 长期是 64 字节,而苹果 M 系列芯片用的是 128 字节缓存行——为移动端能效做的取舍,也意味着跨平台的高性能代码不能把 64 当成宇宙常数。另外在多线程场景下,如果两个核心各自频繁写同一缓存行里的不同变量,缓存一致性协议会让这行数据在两个核心之间来回踢皮球,这就是所谓的“伪共享”,是数据摆放问题的并发版。
技术论证之后,Acton 转入哲学段,也是争议最大的部分。他把矛头对准了“默认面向对象”的工程文化:虚函数调用、堆上散落的对象、指针乱跳的引用关系,每一个都在破坏缓存的连续性;而“为了未来可能的扩展”设计的通用抽象,往往在当下就是纯粹的税。
他那句被引用最多的话大意是:我们不解决通用问题,我们解决的是具体问题。通用方案解决的是通用问题,而你手里那个问题并不通用。在 Acton 看来,不加辨别地套用抽象,本质上是把工程决策让渡给了习惯。
需要说明的是,把这段读成“面向对象已死”是误读。Acton 的立场更精确:抽象不是免费的,每一次抽象都要付代价,而付不付这个代价,应该由数据和访问模式说了算,不是由教条说了算。他在演讲里也承认,工具用在对的地方就是好工具——他反对的是把某种范式当成默认信仰。
最后收束成方法论:数据导向设计(Data-Oriented Design,DOD)不是让你去写汇编,也不是放弃高级语言,而是一套决策顺序——先回答数据的四个问题,再按访问模式决定内存布局,然后才写变换逻辑,最后用性能工具验证,而不是凭感觉判断。
这套思路此后在游戏工业里结出了果实。最著名的是实体-组件-系统(ECS)架构:把“实体”从一个大对象拆成一列列组件数组,系统按列批量处理——本质上就是 SOA 思想的结构化落地。Unity 的 DOTS 技术栈把 DOD 做进了主流商业引擎的官方路线,据公开报道其落地过程几经调整,但《守望先锋》团队在 GDC 2017 公开的 ECS 实践、以及各家自研引擎对“数据布局”的重视,足以说明这堂 2014 年的课如何改变了行业默认值。另一层延伸在科学计算领域早已是常识:NumPy、Pandas 之所以快,正是因为它们把同类型数据连续存放、整列批量处理——很多 Python 用户每天在享受 DOD 的红利而不自知。
这堂课的硬核部分证据充分:缓存层级对热循环性能的主导地位、AOS 与 SOA 的数倍差距、内存墙的物理趋势,都可以用 perf、VTune、Instruments 等工具在自己的机器上复现,属于可测量、可证伪的主张,这也是它十年不衰的根本原因。
但有三处需要打折听取。其一,演示的数倍加速针对的是“每帧扫过海量小对象”这种游戏引擎典型负载,不能外推到所有程序——对一个瓶颈在磁盘和网络上的业务系统,改数据布局大概率是白费劲,Acton 讨论的语境始终是热路径上的热数据。其二,对面向对象的批判是修辞层面的简化:现代编译器对连续布局的代码能自动向量化、自动内联,但对指针乱跳的结构无能为力——这恰恰反过来支持 DOD,不过它同时说明问题不在“对象”这个概念,而在“对象放在堆上、用指针串起来”这个默认实现。其三,DOD 常伴随可读性代价:按字段拆散的数据让调试器和断点不再直观,团队协作时这类代码需要更强的约定和注释,这是真实的工程成本,演讲里着墨不多。
第一,动手前给数据做一张“体检表”。 把 Acton 的四个问题写成你设计文档的第一节:数据量多大、生命周期多长、读写频率多高、访问模式是扫还是跳。热路径上的关键数据结构,先回答这四问再决定布局。你会发现很多“要不要加一层抽象”的争论,答案就藏在这张表里。
第二,用测量代替信仰。 性能是工程事实,不是观点。改动前后跑一次 perf stat -e cache-misses(macOS 用 Instruments,GPU 用对应 profiler),看缓存未命中数有没有真的降下来。从这堂课学到的最重要习惯是:任何“我这样写更快”的说法,包括 Acton 自己的,都要落在计数器上验一遍。
第三,从最热的一个循环开始练手。 不要试图把整个系统改造成 DOD。挑一个 profiler 里最烫的循环,把它的输入数据从对象数组重构成字段数组,对比耗时。一次成功的重构经验,比十篇讲缓存的博客更能改变你写代码时的直觉。顺带一提,如果你写 Python,用 NumPy 把逐对象循环改成向量化运算,就是在做同构的练习。
flowchart TD
A["程序的本质<br/>是数据变换"] --> B["先给数据做体检<br/>多少·多久变·怎么访问"]
B --> C["按访问模式摆数据<br/>SOA 按列连续存放"]
C --> D["缓存行装满有效数据<br/>预取器顺流喂料"]
D --> E["未命中大减<br/>自动向量化顺水推舟"]
E --> F["热循环快出数倍<br/>且更省电"]
B --> G["默认对象写法<br/>AOS 整对象散落堆上"]
G --> H["只为几个字段<br/>拖回整行 64 字节"]
H --> I["缓存未命中<br/>CPU 空等上百纳秒"]
I --> J["性能差数倍<br/>抽象变成了税"]
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
