PHP中while(true)和(;;)之间有什么区别?

时间:2020-12-24 19:21:09

Is there any difference in PHP between while(true) and for(;;) besides syntax and readability?

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

Edit: I would not consider this a duplicate - I want to know the answer specific to PHP. Is there any real difference as far as the engine is concerned? Do they compile to the same thing? Do they have equal performance?

编辑:我不认为这是重复 - 我想知道PHP特有的答案。就发动机而言,有什么真正的区别吗?他们编译成同样的东西吗?他们有同等的表现吗?

Edit 2: I would also not consider the relative performance and associated OpCodes to be based on opinion. There is scope for opinion in the readability but this is explicitly not the question.

编辑2:我也不会认为相对表现和相关的OpCodes是基于意见。在可读性方面存在意见范围,但这显然不是问题。

1 个解决方案

#1


90  

Ok, so first off, let me say this: Use while(true), as it gives the most semantic meaning. You need to parse for (;;) as it's not something you see often.

好吧,首先,让我这样说:使用while(true),因为它给出了最大的语义含义。你需要解析(;;),因为它不是你经常看到的东西。

With that said, let's analyze:

话虽如此,让我们分析一下:

Opcodes

The code

代码

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

Compiles down to the opcodes:

编译到操作码:

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

So basically, it does a check if "true", and if not, jumps to the 4th opcode which is the echo opcode). Then it breaks (which is really just a static jump to the 4th opcode). Then the end of the loop would be an unconditional jump back to the original check

所以基本上,它会检查“true”,如果不是,则跳转到第4个操作码,即echo操作码。然后它中断(这实际上只是静态跳转到第4个操作码)。然后循环的结束将是无条件跳回到原始检查

Compare that to:

比较一下:

for (;;) {
    break;
}
echo "hi!";

Compiles down to:

编译为:

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

So we can immediately see that there's an extra opcode in the for(;;) version.

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

Opcode Definitions

JMPZ(condition, position)

This opcode jumps if the condition is false. If it is true, it does nothing but advance one opcode.

如果条件为假,则此操作码跳转。如果是真的,它只会推进一个操作码。

JMPZNZ(condition, pos1, pos2)

This opcode jumps to pos1 if the condition is true, and pos2 if the condition is false.

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

JMP(position)

This opcode always jumps to the opcode at the specified position.

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

BRK(level, position)

This breaks level levels to the opcode at position

这会将级别级别中断到位置上的操作码

ECHO(string)

Outputs the string

输出字符串

Are They The Same

Well, looking at the opcodes, it's clear that they are not identical. They are ==, but not ===. The while(true) loop does a conditional jump followed by code followed by an unconditional jump. The for(;;) loop does a conditional jump, followed by code, followed by an unconditional jump, followed by another unconditional jump. So it does an extra jump.

那么,看看操作码,很明显它们并不相同。它们是==,但不是===。 while(true)循环执行条件跳转,然后是代码,后跟无条件跳转。 for(;;)循环执行条件跳转,然后是代码,接着是无条件跳转,然后是另一个无条件跳转。所以它做了额外的跳跃。

Opcache

In 5.5, the Optimizer portion of opcache will optimize static conditional jumps.

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

So that means the while(true) code will optimize down to:

这意味着while(true)代码将优化到:

0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")

And for(;;) loop becomes:

并且对于(;;)循环变为:

0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")

This is because the optimizer will find and optimize out jump-chains. So if you're using 5.5's built-in opcache, they will be identical...

这是因为优化器将找到并优化跳链。所以如果你使用5.5的内置opcache,它们将是相同的......

Caution

This is a complete and utter micro-optimization to base a decision on. Use the readable one. Don't use one based on performance. The difference is there, but it's trivial.

这是一个完整的,完全的微观优化,可以作出决定。使用可读的。不要使用基于性能的。差异在那里,但它是微不足道的。

#1


90  

Ok, so first off, let me say this: Use while(true), as it gives the most semantic meaning. You need to parse for (;;) as it's not something you see often.

好吧,首先,让我这样说:使用while(true),因为它给出了最大的语义含义。你需要解析(;;),因为它不是你经常看到的东西。

With that said, let's analyze:

话虽如此,让我们分析一下:

Opcodes

The code

代码

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

Compiles down to the opcodes:

编译到操作码:

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

So basically, it does a check if "true", and if not, jumps to the 4th opcode which is the echo opcode). Then it breaks (which is really just a static jump to the 4th opcode). Then the end of the loop would be an unconditional jump back to the original check

所以基本上,它会检查“true”,如果不是,则跳转到第4个操作码,即echo操作码。然后它中断(这实际上只是静态跳转到第4个操作码)。然后循环的结束将是无条件跳回到原始检查

Compare that to:

比较一下:

for (;;) {
    break;
}
echo "hi!";

Compiles down to:

编译为:

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

So we can immediately see that there's an extra opcode in the for(;;) version.

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

Opcode Definitions

JMPZ(condition, position)

This opcode jumps if the condition is false. If it is true, it does nothing but advance one opcode.

如果条件为假,则此操作码跳转。如果是真的,它只会推进一个操作码。

JMPZNZ(condition, pos1, pos2)

This opcode jumps to pos1 if the condition is true, and pos2 if the condition is false.

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

JMP(position)

This opcode always jumps to the opcode at the specified position.

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

BRK(level, position)

This breaks level levels to the opcode at position

这会将级别级别中断到位置上的操作码

ECHO(string)

Outputs the string

输出字符串

Are They The Same

Well, looking at the opcodes, it's clear that they are not identical. They are ==, but not ===. The while(true) loop does a conditional jump followed by code followed by an unconditional jump. The for(;;) loop does a conditional jump, followed by code, followed by an unconditional jump, followed by another unconditional jump. So it does an extra jump.

那么,看看操作码,很明显它们并不相同。它们是==,但不是===。 while(true)循环执行条件跳转,然后是代码,后跟无条件跳转。 for(;;)循环执行条件跳转,然后是代码,接着是无条件跳转,然后是另一个无条件跳转。所以它做了额外的跳跃。

Opcache

In 5.5, the Optimizer portion of opcache will optimize static conditional jumps.

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

So that means the while(true) code will optimize down to:

这意味着while(true)代码将优化到:

0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")

And for(;;) loop becomes:

并且对于(;;)循环变为:

0: BRK(1, 2)
1: JMP(0)
2: ECHO("hi!")

This is because the optimizer will find and optimize out jump-chains. So if you're using 5.5's built-in opcache, they will be identical...

这是因为优化器将找到并优化跳链。所以如果你使用5.5的内置opcache,它们将是相同的......

Caution

This is a complete and utter micro-optimization to base a decision on. Use the readable one. Don't use one based on performance. The difference is there, but it's trivial.

这是一个完整的,完全的微观优化,可以作出决定。使用可读的。不要使用基于性能的。差异在那里,但它是微不足道的。