PHP可以循环最大迭代次数吗?

Rob*_*ade 10 php loops

给定正确的配置,一个非常简单的进程和足够的内存,PHP对循环中的迭代次数有一个上限,或者它会继续执行,直到你耗尽内存,达到最大执行时间,或者在其他一些中出现故障办法?

如果是这样,各种类型的循环是不同的?虽然,为...做,为,foreach?

例如:

<?php 
for ($i=0; $i<999999999999999999; $i++) {
  echo "$i<br/>";
};
Run Code Online (Sandbox Code Playgroud)

我意识到这有点荒谬,但这主要是我对PHP限制的好奇心.我在文档中找不到任何内容,或者在SO上讨论这个具体问题.

我确实在一个运行PHP 7.1内置服务器的本地开发环境中运行这个脚本,该环境运行在3.1GHz Intel Core i7 MacBook Pro上,内存为16GB,max_execution_time零为零.在大约720,000之后,浏览器本身会达到它自己的限制并冻结.我确实通过CLI运行了同样的测试,虽然花了很长时间,它确实执行并运行但我最终手动停止了它.

ome*_*itz 5

浏览器会冻结,因为它不会得到响应,除非它得到一个500或任何其他错误状态/响应.从理论上讲,PHP可以无限期地运行.

例如,我使用这样的东西来处理后台的一些"工作":

while(true) {
    // and I do some wonders here
    // if some conditions are met
}
Run Code Online (Sandbox Code Playgroud)

当涉及到你的浏览器时,是的 - 它会在等待200 OK响应代码时冻结,因为Web服务器TimeOut配置,PHP的max_execution_time设置(和其他)......以及许多其他因素,而不是提及数据的大小,这些响应代码将无法到达传输到您的浏览器,它会做浏览器的实际"撞车"在你迭代和呼应数的情况下0999999999999999999.

您的for循环将到达它的目的地999999999999999999(可能不在您的浏览器中,但在终端中定义),除非其他东西停止或打破它(即CTRL + C,条件max_execution_time等).


Mon*_*eus 5

TL;博士

PHP很乐意循环,假设它有足够的资源,并且该进程不会被操作系统,Apache,用户等终止...


您对PHP的浏览器问题感到困惑.浏览器无法处理如此多的渲染,因此echo "$i<br/>";崩溃或冻结等等.通过在将$i输出缓冲区发送到浏览器之前将这么多放入输出缓冲区,PHP也可能耗尽内存.

尝试正确地对代码进行基准测试,您将很快得到答案:

// Let's set the start timer
$start = microtime(true);

// Add or remove 9's as you please
for($i=0; $i<999999999999999999; ++$i){}

// How many seconds did this take to complete?
echo (microtime(true) - $start).' seconds<br/>';

// What was the peak memory usage during this code execution?
echo memory_get_peak_usage(true).' bytes used';
Run Code Online (Sandbox Code Playgroud)

假设Apache/PHP /您的浏览器没有超时,那么您应该看到结果; 如果没有那么去命令行.


The*_*aot 5

999999999999999999超出了可以表示的最大安全整数.如果你问PHP 9007199254740992 + 1它会告诉你多少钱9007199254740992.换一种说法:

<?php var_dump ((9007199254740992 + 1) === 9007199254740992);
Run Code Online (Sandbox Code Playgroud)

输出bool(true).

这是浮点数的限制.因此,您的迭代变量$i将无法到达999999999999999999.您已经有效地创建了一个无限循环.

您可以考虑9007199254740992限制.当然,这是因为PHP用于变量的数据类型(double,又名IEEE 754 binary64).


如果使用无限循环并尝试计算迭代次数,则会遇到同样的问题.理论上你可以使用一个可以处理任意大整数的库......但是没有理由说PHP会停止,至少在硬件开始失败之前是这样.

琐事:999999999999999999 flop执行100 gigaflop/second即将开始115 days 17 hours 46 minutes 40 seconds.


勘误表:在PHP的64位构建中,可以表示的最大安全整数是9223372036854775807.换一种说法:

<?php var_dump ((9223372036854775808 + 1) === 9223372036854775808);
Run Code Online (Sandbox Code Playgroud)

输出 bool(true)

在线试试.

9223372036854775808大约是一个大于的数量级999999999999999999,因此这个循环在64位构建的PHP中不是无限的.这不是四精度.经过进一步的测试,结果是PHP使用64位整数9223372036854775807,然后切换到double:

<?php
var_dump (serialize(9223372036854775807));
var_dump (serialize(9223372036854775808));
Run Code Online (Sandbox Code Playgroud)

输出

string(22) "i:9223372036854775807;"
string(25) "d:9.2233720368547758E+18;"
Run Code Online (Sandbox Code Playgroud)

在线试试.

同时,32位构建将使用32位整数2147483647然后使用开关加倍.