PHP中 while(true) 和 for(;;) 的区别是什么?

44

除了语法和可读性之外,在PHP中while(true)for(;;)之间有区别吗?


5
@Touchpad 我很好奇知道关于PHP的具体答案。 - Alastair
1
http://codepad.viper-7.com/awq3Mh 通常我会从 while(true) 中看到稍微更快的性能。 - Michael Berkowski
2
@AzizSaleh PHP是编译成C++然后执行的吗?我以为PHP是用C语言编写的,然后编译成自己的字节码。 - Alastair
2
如果你想写得更简洁,你可以使用 while(1) - Al.G.
2
为什么这个问题被暂停,因为它是基于观点的?也许如果这个问题涉及可读性,但它明确排除了这一点。太疯狂了。 - Ian Goldby
显示剩余9条评论
1个回答

94

首先,让我说一下:使用while(true),因为它给出了最语义化的含义。你需要解析for (;;),因为它不是经常见到的东西。

有了这个前提,让我们分析一下:

操作码

这段代码:

while(true) {
    break;
}
echo "hi!";

编译成操作码:
0: JMPZ(true, 3)
1: BRK(1, 3)
2: JMP(0)
3: ECHO("hi!")

基本上,它进行了一个“真”的检查,如果不是,则跳转到第四个操作码(即echo操作码)。然后中断(实际上只是静态跳转到第四个操作码)。然后循环的结尾是一个无条件跳回原始检查。
将其与以下内容进行比较:
for (;;) {
    break;
}
echo "hi!";

编译成:

0: JMPZNZ(true, 2, 4)
1: JMP(0)
2: BRK(1, 4)
3: JMP(1)
4: ECHO("hi!")

因此,我们可以立即看到在 for(;;) 版本中有一个额外的操作码。

操作码定义

JMPZ(condition, position)

如果条件为 false,则此操作码跳转。如果条件为 true,则仅推进一个操作码。

JMPZNZ(condition, pos1, pos2)

如果条件为真,则此操作码跳转到 pos1,如果条件为假,则跳转到 pos2

JMP(position)

此操作码始终跳转到指定位置的操作码。

BRK(level, position)

level 级别中断到 position 操作码处。

ECHO(string)

输出字符串。

它们是相同的吗

好的,从指令码上看,它们不相同。它们是 ==,但不是 ===while(true) 循环执行一个有条件转移,然后是代码,再跟着一个无条件转移。 for(;;) 循环执行一个有条件转移,之后是代码,再跟着一个无条件转移,最后再跟着一个无条件转移。因此,它做了一次额外的跳转。

Opcache

在5.5中,opcache的优化器部分将优化静态条件跳转

这意味着 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,则它们将是相同的...
注意:
这是一种完全微小的优化,在决策基础上过于苛求。请使用易读的那个,不要基于性能使用一个。差异存在,但微不足道。

1
在优化后的 while 版本中,JMP(1) 作为第一条指令有什么意义?这不是相当于无操作吗?为什么它没有被优化掉? - bdesham
1
@bdesham:它似乎被优化掉了:http://lxr.php.net/xref/PHP_TRUNK/ext/opcache/Optimizer/pass3.c#134。看起来 JMP(2); JMP(0); 也会被优化为 JMP(2);,但我无法立即确定它是否会进一步优化为 NOP... - ircmaxell
1
优秀的分析!相同的行为导致相同的优化(理想情况下应该如此),而更语义化的构造在预优化时具有较少的操作码,使其成为这种微观优化的“更好”选择,进一步强调了while(true)应该是首选。 - Brian S
3
使用“while(true)”会给予代码最明显的语义意义。你需要解析“(;;)”因为它不是经常看到的东西。个人认为,我把“(;;)”解释成一个哭脸,因为为什么要写无限循环呢?这让我感到难过。 - Mike G
2
@mikeTheLiar 任何事件循环在技术上都是一个简单的无限循环,用于轮询输入。至于“你需要解析for (;;)”这部分——实际上在C中经常使用它代替while (1),因为代码检查工具对for变体的抱怨较少[需要引证]。 - TC1
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接