【问题标题】:How to reduce virtual memory by optimising my PHP code?如何通过优化我的 PHP 代码来减少虚拟内存?
【发布时间】:2011-06-01 20:03:37
【问题描述】:

我当前的代码(见下文)使用 147MB 的虚拟内存! 我的提供程序默认分配了 100MB,并且该进程在运行后被终止,导致内部错误。 该代码使用 curl multi 并且必须能够循环超过 150 次迭代,同时仍然最小化虚拟内存。下面的代码仅设置为 150 次迭代,仍然会导致内部服务器错误。在 90 次迭代时,问题不会发生。

如何调整我的代码以降低资源使用/虚拟内存?

谢谢!

<?php

    function udate($format, $utimestamp = null) {
      if ($utimestamp === null)
        $utimestamp = microtime(true);
      $timestamp = floor($utimestamp);
      $milliseconds = round(($utimestamp - $timestamp) * 1000);
      return date(preg_replace('`(?<!\\\\)u`', $milliseconds, $format), $timestamp);
    }

$url = 'https://www.testdomain.com/';
$curl_arr = array();
$master = curl_multi_init();

for($i=0; $i<150; $i++)
{
    $curl_arr[$i] = curl_init();
    curl_setopt($curl_arr[$i], CURLOPT_URL, $url);
    curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_multi_add_handle($master, $curl_arr[$i]);
}

do {
    curl_multi_exec($master,$running);
} while($running > 0);

for($i=0; $i<150; $i++)
{
    $results = curl_multi_getcontent ($curl_arr[$i]);
    $results = explode("<br>", $results);
      echo $results[0];
      echo "<br>";
      echo $results[1];
      echo "<br>";
      echo udate('H:i:s:u');
      echo "<br><br>";
      usleep(100000);
}

?>

【问题讨论】:

  • @dqhendricks:“我的提供商默认分配了 100MB”== 共享主机。
  • @dqhendricks, @thirtydot:在 Linux 上使用 WHM。我已经用服务器信息更新了我的问题。通过命令行而不是apache运行它,我不明白你的意思?对不起..
  • @iCeR:您正在测试的测试页有多少字节?
  • 您的提供商是否允许您运行二进制文件?使用本机代码执行此操作可以节省大量内存消耗...
  • @thirtydot:814 字节(磁盘上 4,096)

标签: php curl performance virtual-memory


【解决方案1】:

根据您的最后评论..

下载RollingCurl.php

希望这足以让您的 API 中的生活日光成为垃圾邮件。

<?php

$url = '________';
$fetch_count = 150;
$window_size = 5;


require("RollingCurl.php");

function request_callback($response, $info, $request) {
    list($result0, $result1) = explode("<br>", $response);
    echo "{$result0}<br>{$result1}<br>";
    //print_r($info);
    //print_r($request);
    echo "<hr>";
}


$urls = array_fill(0, $fetch_count, $url);

$rc = new RollingCurl("request_callback");
$rc->window_size = $window_size;
foreach ($urls as $url) {
    $request = new RollingCurlRequest($url);
    $rc->add($request);
}
$rc->execute();

?>

看了你的问题,我看到了this comment

如果意图是域名抢夺, 然后使用已建立的一种 服务是更好的选择。您的 脚本实现几乎不像 重要的实际连接和 延迟。

我同意这个评论。

另外,您似乎已经发布了大约 七百次

https://stackoverflow.com/users/558865/icer
https://stackoverflow.com/users/516277/icer

How can I adjust the server to run my PHP script quicker?
How can I re-code my php script to run as quickly as possible?
How to run cURL once, checking domain availability in a loop? Help fixing code please
Help fixing php/api/curl code please
How to reduce virtual memory by optimising my PHP code?
Overlapping HTTPS requests?
Multiple https requests.. how to?

你必须一遍又一遍地问同样的问题,这不是告诉你you're doing it wrong吗?

你的This comment

@mario:干杯。我在竞争 其他 2 家特定的公司 ccTLD。他们是游戏新手 他们正在抢购这些域名 慢时间(最多 10 秒后 吹扫时间)。我只是慢了一点 目前。

如果您在抢购过期域名方面认真尝试击败两家公司,我相当肯定共享主机帐户上的 PHP 是错误的工具。

【讨论】:

  • 我完全同意你的评论,OP应该为这种脚本获得一个专用或VPS。
【解决方案2】:

150 个查询中的每一个的结果都存储在 PHP 内存中,您的证据表明这是不够的。唯一的结论是您不能在内存中保留 150 个查询。您必须有一种流式传输到文件而不是内存缓冲区的方法,或者只是减少查询数量并批量处理 URL 列表。

要使用流,您必须将CURLOPT_RETURNTRANSFER 设置为0 并为CURLOPT_WRITEFUNCTION 实现回调,PHP 手册中有一个示例:

http://www.php.net/manual/en/function.curl-setopt.php#98491

function on_curl_write($ch, $data)
{
  global $fh;
  $bytes = fwrite ($fh, $data, strlen($data));
  return $bytes;
}

curl_setopt ($curl_arr[$i], CURLOPT_WRITEFUNCTION, 'on_curl_write');

在回调中获取正确的文件句柄留待读者解决。

【讨论】:

  • @Steve-o:对 API 的查询运行相同的 URL 150 多次。这样做的原因是进行持续检查并通知我更新/更改。 API 目前正在阻止相当多的事情。我怎样才能将上面的代码流式传输到文件?减少查询的数量是不可能的,如果它会增加的话,除非你有一种方法可以分批地一个接一个地处理它们。非常感谢,谢谢。
  • 150 个长度为 814 的文件加起来不到一兆字节。我认为流式传输到文件不会在这里产生任何影响。
  • @Billy 除了清除 CURL 句柄之外,这是这里唯一的可控变量。
  • @Steve-o:感谢有关流的更新。修改以适应我上面的代码进行测试时遇到了一些麻烦。对不起。
  • @Steve-o:没关系.. 现在看到了 :) 谢谢.. 马上测试。读懂我的想法!
【解决方案3】:
<?php

echo str_repeat(' ', 1024); //to make flush work

$url = 'http://__________/';
$fetch_count = 15;
$delay = 100000; //0.1 second
//$delay = 1000000; //1 second


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);


for ($i=0; $i<$fetch_count; $i++) {

    $start = microtime(true);

    $result = curl_exec($ch);

    list($result0, $result1) = explode("<br>", $result);
    echo "{$result0}<br>{$result1}<br>";
    flush();

    $end = microtime(true);

    $sleeping = $delay - ($end - $start);
    echo 'sleeping: ' . ($sleeping / 1000000) . ' seconds<hr />';
    usleep($sleeping);

}

curl_close($ch);

?>

【讨论】:

  • @thirtydot:谢谢你 - 设置一个时间戳,它每 900 毫秒输出一次:/ 有什么方法可以加快速度?
  • @iCeR:你能描述一下这 900 毫秒的花费吗?例如,将$result = file_get_contents($url); 更改为$start_get = microtime(true); $result = file_get_contents($url); $end_get = microtime(true); echo $end_get - $start_get;
  • @thirtydot: 可以获取 $url 的内容,它的范围从 755 毫秒到 932 毫秒。之后只需额外的 9 毫秒。这很奇怪,因为使用 curl_multi 它可以多次加载 url 并在 50 毫秒或更短的时间内将它们吐出..
  • 好吧,这就解释了。你不能用这个当前的代码让它更快。那么,下一个策略:API 服务器是否支持 HTTP keepalives(它可能会)?如果是这样,我们可以利用它们来加快速度(避免每次都打开新连接)。 file_get_contents() 不使用保活。如果您不知道如何确定是否支持 keepalive,请告诉我。
  • curl_multi 能做到这么快的原因是因为它只是在开始时 请求 URL 150 次,“没有”延迟.
猜你喜欢
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
  • 2019-03-01
  • 1970-01-01
  • 2015-03-01
  • 1970-01-01
  • 2022-01-26
相关资源
最近更新 更多