ZipArchive::addFile()是否会干扰hrtime()的计时准确性?
问题:ZipArchive::addFile()导致hrtime计时不准?
我写了下面的循环,想让它在10秒后停止:
//open archive $zip $start = hrtime(true); while(true) { $zip->addFile($files[$i++]); $end = hrtime(true); $time = ($end - $start) / 1e+9; // convert to seconds if( $time > 10.0) { break; } } echo $i;
但计时器没法准确在10秒后停止。换成用sleep模拟工作的循环,就会正常在10秒左右停止:
//open archive $zip $start = hrtime(true); while(true) { sleep(1); // simulate work $end = hrtime(true); $time = ($end - $start) / 1e+9; // convert to seconds if( $time > 10.0) { break; } } echo $i;
想问下ZipArchive::addFile()会不会影响硬件计时器,导致时间差计算出错?我知道可以用microtime(true),但它在虚拟机环境里准确性可能更低。
解答
首先,ZipArchive::addFile()不会影响硬件计时器,hrtime(true)读取的是系统级的高精度计时器,和单个PHP扩展的操作没有关联。问题出在你的循环逻辑上:
- 用sleep模拟的循环中,每次
sleep(1)后立刻检查时间,逻辑是“完成一次工作后判断是否超时”,而且sleep本身是阻塞操作,时间计算的时机很稳定。 - 但在addFile的循环里,你是每次调用addFile之后才检查时间。如果
addFile执行耗时较长(比如处理大文件、磁盘IO速度慢),那这次操作可能直接让总耗时超过10秒很多,才会触发break。举个例子:如果第9次循环后总耗时是9秒,第10次addFile花了2秒,执行完检查时总耗时已经是11秒,自然停止时间不准。
另外,hrtime(true)本身是可靠的,它不会被PHP的IO操作干扰,问题完全是循环内的时间检查时机不对。如果要更精准控制超时,应该在每次循环开始前先检查时间,而非做完耗时操作后再检查:
//open archive $zip $start = hrtime(true); $i = 0; while(true) { // 先检查是否超时,再执行耗时操作 $end = hrtime(true); $time = ($end - $start) / 1e+9; if($time > 10.0) { break; } $zip->addFile($files[$i++]); } echo $i;
这样就能保证一旦超时就立刻停止,不会因为某次addFile的耗时导致超时过多。microtime(true)确实在虚拟机环境可能存在精度问题,所以继续使用hrtime是更优的选择。
内容的提问来源于stack exchange,提问作者theking2
相关产品推荐
相关产品推荐

