C++ 高效编程:从 OOP 到 DOD 的思维转变

Writing Efficient C++ Code

C++ 高效编程:从 OOP 到 DOD 的思维转变

虽然高级语言开发便捷,但在游戏和实时数据处理等对性能要求严苛的领域,C++ 依然是首选。然而,仅选择 C++ 并不够,盲目遵循面向对象编程(OOP)可能导致内存碎片化和缓存未命中,严重拖慢程序。文章深入解析了数据导向设计(DOD)理念,强调在编码时应优先考虑数据在内存中的布局,而非仅仅封装对象。通过理解 CPU 缓存机制和内存层次结构,开发者可以优化数据结构,减少指针跳转,从而显著提升代码在多线程环境下的并行能力和整体执行效率。

盲目遵循面向对象编程会带来其他陷阱,比如人们会本能地将使用的每个功能都包装在自己的封装层中,试图简化接口或使其看起来更优雅,但这往往会增加运行时开销。
  1. asveikau

    这篇文章让我想起了 2000 年代开始流行的一些性能优化建议。核心思想是:不要为了降低算法复杂度而引入大量依赖指针的数据结构。把所有东西都塞进 vector 里吧。虽然计算机科学教科书上会说某些算法更慢,但如果它们能全部塞进缓存,那就无所谓了。满世界追着指针跑导致的缓存缺失,带来的伤害更大。

  2. Jeaye

    既然说到这儿,有人见过涉及垃圾回收(GC)的数据导向设计(DoD)资源吗?数据导向设计的很多内容都聚焦于对象池(arena),但这并不总是可行的,尤其是当代码的生命周期模型需要 GC 时(不管出于什么原因)。

    我觉得 DoD 运动正在缓慢但深刻地改变系统编程的方式,但在不同场景下如何实践,现有的资料仍然不足。我真的很想在我的工作领域更多地应用这些理念,我的领域也是 C++,但似乎理论呈现与实际应用之间存在鸿沟。

    具体来说,我正在用 C++ 构建一个 Clojure 方言的动态语言运行时。该运行时必须支持垃圾回收、类型擦除和高度多态。所以我肯定不能把所有东西都搞成 SoA 或 AoS。是的,我可以打包数据,尽可能在编译器/运行时代码以及通过逃逸分析生成的代码中避免 GC。但剩下的那 80% 甚至更多的部分该怎么办呢?也许这个运行时与 DoD 背道而驰,但我通常认为事物是渐变的,而非非黑即白。

  3. MaxBarraclough

    文章完全没有提到分支预测、上下文切换或同步。根据你具体在做什么,这些因素可能影响巨大。关于多线程并行化和 SIMD 的提及也非常简略。

    高性能编程是个大话题。单篇博客的篇幅太宽泛,自然只能对 C++ 和计算机架构进行浅尝辄止的讨论。考虑到这一点,这篇文章不算差,但我认为它选错了形式。博客系列甚至书籍会更适合。

  4. hn_submit

    我几乎每天写 C++,但从未需要为速度进行优化。即使写出直白简单的代码,速度也已经快得飞起。

  5. chombier

    几周前 HN 上发过一个很不错的数据库查询语言库 [1],其约束是所有内容必须符合 6NF。

    当时我觉得这天然适合用在数据导向设计/ECS 系统中来运行复杂查询。我想知道是否有人尝试过,以及这在实践中是否真的有效?

    [1] https://prela-lang.org/tutorial/

  6. 112233

    "本文最初以波兰语发表于 2013 年第 4 期"——很多极好的建议。遗憾的是,过去十年 C++ 的发展走向让编写高效、简洁的底层代码变得越来越难 :(

  7. add2

    在大多数情况下,性能提升微乎其微,代码反而变得更复杂了。

    "过早优化是万恶之源"

  8. FpUser

    我最新的 C++ 项目是一个评估引擎,涵盖各种精算类任务,比如计算保险风险等。在 16 核服务器上,批量计算的典型性能可达每秒数百万到数千万次评估。这里有个技巧:内部会从 DSL 即时编译(JIT)规则为可执行代码。解释器模式(主要用于审计模式)大约慢 3-5 倍,但这速度依然快得离谱。

同日更多故事

2026-09-27