好的,首先,让我这样说:使用while(true),因为它提供了最多的语义含义。您需要解析 for (;;),因为它不是您经常看到的。
说了这么多,我们来分析一下:
操作码
代码
while(true) {
break;
}
echo "hi!";
编译成操作码:
0: JMPZ(true, 3)
1: BRK(1, 3)
2: JMP(0)
3: ECHO("hi!")
所以基本上,它会检查是否为“真”,如果不是,则跳转到第四个操作码,即回显操作码)。然后它会中断(这实际上只是到第四个操作码的静态跳转)。那么循环的结束就是无条件跳回原来的检查
比较一下:
for (;;) {
break;
}
echo "hi!";
编译为:
0: JMPZNZ(true, 2, 4)
1: JMP(0)
2: BRK(1, 4)
3: JMP(1)
4: ECHO("hi!")
所以我们可以立即看到for(;;) 版本中有一个额外的操作码。
操作码定义
JMPZ(条件,位置)
如果条件为false,则此操作码会跳转。如果是true,它只会前进一个操作码。
JMPZNZ(条件, pos1, pos2)
如果条件为真,此操作码跳转到pos1,如果条件为假,则跳转到pos2。
JMP(位置)
这个操作码总是跳转到指定位置的操作码。
BRK(级别,位置)
这会将level 级别打破为position 处的操作码
回声(字符串)
输出字符串
他们是一样的
好吧,看看操作码,很明显它们并不相同。他们是==,但不是===。 while(true) 循环执行条件跳转,然后是代码,然后是无条件跳转。 for(;;) 循环执行条件跳转,然后是代码,然后是无条件跳转,然后是另一个无条件跳转。所以它做了一个额外的跳跃。
Opcache
在 5.5 中,opcache 的优化器部分将 optimize static conditional jumps。
这意味着while(true) 代码将优化为:
0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")
而for(;;) 循环变为:
0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")
这是因为优化器会找到并优化出跳转链。因此,如果您使用 5.5 的内置 opcache,它们将是相同的......
注意
这是一个完整而彻底的微优化,可作为决策依据。使用可读的。不要基于性能使用一个。区别是存在的,但微不足道。