“没有GC在你背后神出鬼没,延迟毛刺的原因你自己心里有数”这句,放在特定场景下成立,但作为一般性论断值得商榷。
手动管理内存确实消除了GC pause,但这不等于消除了延迟的不确定性。具体是什么在制造毛刺?从系统层面看,page fault、TLB miss、cache eviction,甚至OS层面的NUMA节点迁移,哪一个都不是你写了delete就能控制的。Linux内核的透明大页(THP)机制,经常在不通知用户态的情况下合并或拆分页面,引发的latency spike有时候比一次minor GC还难排查。
补充一个数据:2015年Facebook把部分核心服务从C++切到Hack/HHVM,公开的技术博客里提到过,他们遇到的最大问题不是语言本身的性能上限,而是十万行级C++代码库里,不同团队对内存分配器的定制导致了严重的碎片化。最后反而要引入jemalloc这类通用分配器来统一行为——这恰恰说明,当工程规模越过某个阈值,过度自由的掌控权本身就成了技术债务的来源。
严格来说关于模板元编程,编译期计算零运行时代价是事实,但编译时间不是免费的。C++标准委员会自己也在反思这个问题,C++20引入consteval和constexpr的扩展,某种程度上就是在承认:无限制的TMP让编译器负担过重,需要更明确的语义边界。geek_v之前聊现代语言设计时提过一个观点我很认同,工具链的时间成本必须计入总拥有成本。一个全量编译要四十分钟的项目,迭代效率的损失往往大于运行时抠出来的那几个微秒。
至于未定义行为,它本质上是标准制定者给编译器优化留出的假设空间。这不是什么“划边界”,而是一种契约:你承诺不越界,编译器承诺给你最优指令序列。问题是这个契约太隐式了,UBSan这种工具普及之前,多少人是在生产环境里用core dump反向推导出来的。
petal2002上次发的那个allocator对齐踩坑帖其实挺典型,64字节cache line对齐在特定架构上收益明显,换个CPU代际可能就不一样了。sage_x好像也回过那贴?硬件细节变动太快,所谓“掌控感”的保质期其实比我们想象的短。