为何D语言中相同for循环第二次运行速度更快?
为啥连续两个一模一样的for循环,第二个总是跑得更快?
嘿,你碰到的这个现象其实是**CPU缓存预热(Cache Warming)**搞的鬼,这是硬件层面的通用性能逻辑,和你在对比的D语言内置数组、普通指针没啥直接关系,咱们来拆解清楚:
先把你的代码补全方便理解
我先把你没写完的代码补全(推测你是在做内存读写的性能测试):
import std.stdio : writeln; import std.datetime : StopWatch; import core.stdc.stdlib : malloc, free; void main() { immutable N = 1_000_000_000; StopWatch sw; uint* ptr = cast(uint*)malloc(uint.sizeof * N); // 第一个测试循环 sw.start(); for (uint i = 0; i < N; ++i) { ptr[i] = i; // 不管是读还是写,逻辑一致 } sw.stop(); writeln("第一个循环耗时: ", sw.peek()); // 重置计时器,跑第二个完全相同的循环 sw.reset(); sw.start(); for (uint i = 0; i < N; ++i) { ptr[i] = i; } sw.stop(); writeln("第二个循环耗时: ", sw.peek()); free(ptr); }
背后的核心原因:CPU缓存机制
CPU的运算速度比主存快好几个数量级,所以硬件设计了多级缓存(L1、L2、L3)来缩小这个差距:
- 第一次循环的时候:你要访问的内存块还没被加载到CPU缓存里,每一次内存读写都会触发「缓存缺失」——CPU得停下来等数据从慢得要死的主存加载到缓存,这个过程要花几十甚至几百个CPU周期,自然耗时久。
- 第二次循环的时候:经过第一次循环的“折腾”,目标内存区域已经被完整加载到CPU缓存里了,此时所有的内存访问都是「缓存命中」,速度是缓存级别的(仅几个CPU周期),所以整体耗时直接砍半甚至更少。
怎么验证这个结论?
你可以试试这几个小实验:
- 交换两个循环的顺序:先跑原来的第二个循环,再跑第一个,你会发现原来慢的那个现在变快了,顺序一变结果就反转,说明问题完全在缓存,不在循环本身。
- 提前预热缓存:在正式计时前先跑一次无计时的循环,再开始测,两次计时的结果会变得差不多。
- 换块新内存:第二个循环去访问另一块malloc出来的全新内存,此时第二个循环也会变慢,因为新内存没被缓存过。
和D语言数组/指针的关系
别担心,这不是D语言的问题——不管你用D的内置数组uint[] arr = new uint[N];还是用C风格的malloc指针,只要是连续访问同一块内存,都会出现第二次循环更快的情况,这是所有现代CPU都有的特性,和语言无关。
内容的提问来源于stack exchange,提问作者Betelgeyser
相关产品推荐
相关产品推荐

