PHP程序因大量数据而失败

时间:2016-12-14 01:15:13

标签: php http

我正在编写一个PHP Web程序,它从文件中检索数据并绘制图形。如果我在服务器上的命令行中运行它可以正常工作,并且它可以在浏览器中运行相对少量的数据,但是一旦文件达到1.2或130万行(30个字符/行,那么3.5或4 MB) ),我得到一个HTTP错误500.奇怪的是,它的工作不一致;有125万行,它有时是有效的,有时也不行。 这是代码:

<?php

$wait = $_GET["wait"];
$measure = $_GET["measure"];
$graphsize = $_GET["graphsize"];
$title = "Current";
if ($measure == "CURR") $title = "Current (A)";
if ($measure == "VOLT") $title = "Voltage (V)";
if ($measure == "RES")  $title = "Resistance (Ohms)";

$page = $_SERVER["PHP_SELF"];

$data = array(array("Time", $title));
$datasize = filesize("data.csv")/30;
$x = 0;

$file = fopen("data.csv", "r");
while (($datum = fgets($file)) !== False) {
    $x++;
    if ($x % ($datasize/$graphsize) == 0) {
        $datum = explode(",", $datum);
        $datum[0] = floatval($datum[0]);
        $datum[1] = floatval($datum[1]);
        $data[] = $datum;
    }
}
fclose($file);

if (count($data) == 1) $data[] = array(0,0);

?>

graphing stuff down here, I'm pretty sure this isn't the problem

1 个答案:

答案 0 :(得分:1)

在某些系统上,PHP有两个不同的php.ini文件 - 一个用于apache,另一个用于CLI。通常,CLI ini文件不会对max_execution_time施加任何限制,并且memory_limit的值也很大。这可能解释了为什么它通过CLI运行而不是通过Web服务器运行。

逐行解析文件是明智的,因为这会比一次读取整个文件内容消耗更少的内存。你应该检查fopen的结果,以确保你实际上是打开文件:

$file = fopen("data.csv", "r");
if (!$file) {
    throw new Exception("Could not open data file");
}

如果您的脚本在通过Web服务器访问时返回5XX结果,这通常意味着PHP脚本遇到致命错误情况。我猜你要么a)用完了时间,要么b)内存不足。要找出答案,您需要查看php错误。如果它没有直接输出到您的浏览器,那么您需要弄清楚我们的php日志在哪里。可能存在为此指定的值,或者可能没有。尝试此操作以查看是否设置了值:

echo ini_get("error_log");

如果此值为空,则:

  

如果未设置此指令,则会将错误发送到SAPI错误记录器。例如,它是Apache中的错误日志或CLI中的stderr。

在我的Ubuntu计算机上,此文件在每个域的apache conf文件中设置,如下所示:

ErrorLog /var/www/site_name/log/error.log

但是在你的机器上可能会有一些完全不同的东西。如果找不到它,请考虑使用set_error_handler函数创建自己的自定义错误处理函数,该函数可以拦截错误并将其写入文件或通过电子邮件发送或者只是将其吐出或者其他东西。

检查php.ini为几个设置设置的限制是有用的:

// feel free to add more ini settings to this array if you are curious
$to_check = array("max_execution_time", "memory_limit", "error_log");
foreach($to_check as $setting) {
    echo $setting . ": " . ini_get($setting) . "\n<br>";
}

如果这些值看起来不令人满意,您可能会尝试通过编辑Web服务器的php.ini来尝试使用ini_set 在脚本中更改这些值。但是,我不建议使用后者,因为其中的值设置为保护您的服务器 - 如果您允许脚本运行太长或占用太多内存,您的服务器很容易受到运行的脚本的影响资源。但是,如果您的服务器在safe_mode中运行,则不允许您使用ini_set更改设置。

我还建议您查看php函数memory_get_usage()和microtime()。您可以跟踪脚本中使用的内存和已用时间,以了解在脚本失败之前达到的值。虽然从脚本中回显这些值可能更容易,这意味着很多输出可能不是一个好主意。我建议你把返回的值写成一个文件。类似的东西:

$log_file = "/some/path/to/log/file.txt";
$start_time = microtime(TRUE); // returns a unix timestamp as a float
file_put_contents($log_file, "start time is " . $start_time)
    or die("Unable to write log file");

// your script blah blah blah
$file = fopen("data.csv", "r");
while (($datum = fgets($file)) !== False) {

    // do your script datum stuff blah blah blah

    // write our progress to our log file
    file_put_contents($log_file, "elapsed time is " . (microtime(TRUE) - $start_time))
        or die("Unable to write elapsed time to log file");
    file_put_contents($log_file, "memory consumed is " . memory_get_usage())
        or die("Unable to write memory usage to log file");
}

如果您的脚本失败,那么您可以查看 /some/path/to/log/file.txt 的内容,看看在停止之前使用了多少时间和内存。