PHP fwrite()性能和内存问题

时间:2019-04-30 21:05:29

标签: php performance memory fastcgi

编辑 :最初,我认为此问题与PHP-FPM有关,因为我的主机暗含了此问题(请参阅下文)。我开始配置测试服务器以使用PHP-FPM(cgi-fcgi),并且脚本运行时没有性能/内存问题。我的主机服务器上可能还有其他东西在做奇怪的事情,例如跟踪文件写入并将写入的内容无缘无故地放入内存。有谁知道是否有这样的软件/模块可以做到这一点?同时,我将再次与房东联系...

问题

我有一个PHP脚本,该脚本使用fwrite()将数据写入文件。在运行CloudLinux服务器的共享主机上,性能很慢,并且当需要写入大量数据时内存耗尽。看来问题出在Apache在服务器上使用的PHP-FPM。如果我通过SSH进入服务器并使用PHP-CLI运行相同的脚本,则性能会好得多(快7倍),并且在脚本运行期间内存使用情况几乎保持不变。

我写了一个简单的测试脚本来说明这一点:

echo 'SAPI: ' . php_sapi_name(); // Shows if you're using fcgi or cli
if (php_sapi_name() === 'cli') { // Set appropriate line break char
    $eol = PHP_EOL;
}
else {
    $eol = '<br>';
}
echo $eol;
echo 'Starting fwrite...' . $eol;

$time_start = microtime(true); 
$fh = fopen('/some/path/test-fw.txt', 'w');
$i = 0;
while ($i < 2000000) {
    $str = 'row-' . $i . ': this is a test string abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg ';
    fwrite($fh, $str);
    $i++;
}
echo 'fwrite done!' . $eol;
echo 'Time taken: ' . (microtime(true) - $time_start) . 's' . $eol;
fclose($fh);
echo 'Sleeping for 60s before exiting...';
sleep(60); // Give you some time to check memory usage (in CPanel)

测试结果:

  • 从浏览器中调用时,内存使用量开始于30MB左右,到脚本结束时达到330MB。执行时间约为78秒。
  • 使用PHP-CLI调用时,内存使用量保持在30MB左右。执行时间约为10秒。

内存使用率是CPanel中显示的物理内存使用率。顺便说一下,文件大小约为300MB,所以我在想用fwrite()编写的内容是否也被PHP-FPM放入了内存!

我希望通过在另一个脚本中执行exec('php-cli script.php')来解决此问题,但这没有用。它所做的只是创建一个php-cli进程的子代php-cgi进程。

我的主机的支持人员告诉我:“ CGI会将所有内容都存储到内存中,除非您告诉它'转储'它,并且CGI旨在降低CPU占用率”。我有些困惑,因为我看不到代码中的“转储”内容以释放内存。我的意思是,在我的测试脚本中,除非我明确禁止,否则CGI是否会存储传递给$str的每个fwrite()?如果是这样,我该怎么做(尝试了unset()却没有帮助)?

不幸的是,我无法在共享主机上更改PHP处理程序。否则,我将只使用当前在本地测试服务器上使用的mod_php,而不会出现上述问题。

我想知道是否有人有类似的经验可以指出正确的方向。如果有什么用,我可以使用Inmotion Hosting的Power计划,该计划为我的帐户分配了2GB的物理内存。

要澄清的是: 似乎在调用fclose()并进入睡眠时间后不久,内存就恢复了正常。因此,我确实认为是fwrite()导致了这个问题的出现。 fflush()set_file_buffer($fh, 0)没有帮助。好像内容正在写入磁盘,但同时又保留在内存中,我不知道是什么导致了后者……

0 个答案:

没有答案