给定正确的配置,一个非常简单的进程和足够的内存,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运行了同样的测试,虽然花了很长时间,它确实执行并运行但我最终手动停止了它.
浏览器会冻结,因为它不会得到响应,除非它得到一个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设置(和其他)......以及许多其他因素,而不是提及数据的大小,这些响应代码将无法到达传输到您的浏览器,它会做浏览器的实际"撞车"在你迭代和呼应数的情况下0到999999999999999999.
您的for循环将到达它的目的地999999999999999999(可能不在您的浏览器中,但在终端中定义),除非其他东西停止或打破它(即CTRL + C,条件max_execution_time等).
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 /您的浏览器没有超时,那么您应该看到结果; 如果没有那么去命令行.
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然后使用开关加倍.
| 归档时间: |
|
| 查看次数: |
2384 次 |
| 最近记录: |