【问题标题】:PHP script memory leak issuePHP脚本内存泄漏问题
【发布时间】:2023-03-16 12:17:01
【问题描述】:

我正在从命令行运行下面的 PHP 代码。问题是,它的内存消耗远远超过应有的水平。在我的一生中,我无法弄清楚内存在哪里被消耗。

for ($i=0;$i<100;$i++)  
        {
            $classObject = $classObjects[$i];                       

            echo $i . "   :   " . memory_get_usage(true) . "\n";
            $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap);           
            unset($classDOM);           
        }

根据我的说法,我的脚本消耗的内存在循环的每次迭代之后应该或多或少保持不变。当$scraper-&gt;scrapeClassInfo() 的成员超出范围时,应该释放所有被$scraper-&gt;scrapeClassInfo() 消耗的内存。

这是我得到的输出文件。为简洁起见,我每 10 行显示一次输出:

0   :   5767168
10   :   12058624
20   :   18350080
30   :   24903680
40   :   30932992
50   :   37748736
60   :   43778048
70   :   49807360
80   :   55836672
90   :   62914560
97   :   66846720

Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 44 bytes) in /home/content/60/8349160/html/drexel/simple_html_dom.php on line 1255

最后,据我所知,$scraper-&gt;scrapeClassInfo() 所做的应该不是真正的罪魁祸首,但以防万一,这里是代码:

function scrapeClassInfo($class,$termMap,$subjectMap)
        {
            $ckfile = tempnam ("/tmp", "CURLCOOKIE");
            $ckfile2 = tempnam ("/tmp", "CURLCOOKIE2");
            $ckfile3 = tempnam ("/tmp", "CURLCOOKIE3");         

            $termpage = $termMap[$class['termcode']];
            $subjectpage = $subjectMap[$class['subjectcode']];
            $classpage = $class['classlink'];

            //hit the main page and get cookie
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_URL, $this->mainURL);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_exec($ch);
            curl_close($ch);

            //hit the term page and get cookie
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
            curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile2);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_URL, $termpage);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_exec($ch);
            curl_close($ch);

            //hit the subject page and get cookie
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile3);
            curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile2);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_URL, $subjectpage);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_exec($ch);
            curl_close($ch);

            //hit the class page and scrape
            $ch = curl_init();              
            curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile3);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_URL, $classpage);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            $result = curl_exec($ch);
            curl_close($ch);

            return str_get_html($result);
        }

最后一行调用的方法,str_get_html()Simple HTML DOM Parser的成员

如果有关系,这就是我调用脚本的方式:

/usr/local/php5/bin/php index.php 2&gt;&amp;1 1&gt;output

【问题讨论】:

    标签: php memory-leaks out-of-memory


    【解决方案1】:

    好吧,想通了。显然,这是 5.3 之前的所有 PHP 版本都存在的错误。将CURLOPT_RETURNTRANSFER 设置为true 会导致大量内存泄漏。

    我再次运行脚本,这次调用的是 php 5.3 二进制文件:

    /web/cgi-bin/php5_3 index.php 2>&1 1>output
    

    输出文件如下:

    0   :   6291456
    10   :   9437184
    20   :   10747904
    30   :   11534336
    40   :   11534336
    50   :   11534336
    60   :   11534336
    70   :   11534336
    80   :   11534336
    90   :   11534336
    99   :   11534336
    152.74998211861 sec
    

    这就是我要说的!完全恒定的内存占用。

    【讨论】:

    • 当我写“将 CURLOPT_RETURNTRANSFER 设置为 true”时,我的意思是写“将 CURLOPT_RETURNTRANSFER 设置为 true 会导致大量内存泄漏”。已编辑。
    • 嗯!所以肯定不是CURLOPT_SSL_VERIFYPEER? (见stackoverflow.com/questions/9217238/…
    • @AdamMonsen:不能确定是什么 CURL 选项导致了它。切换到 5.3 二进制解决了这个问题。
    • 好吧,有趣。我很容易在 RHEL 6 上复制 bugs.php.net/bug.php?id=61030,但在任何 Ubuntu 上都不能。两者都有 PHP 5.3。
    【解决方案2】:

    我在您的代码中发现了以下内容。

    1. 删除curl_setopt($ch, CURLOPT_RETURNTRANSFER, true),因为您没有捕获它。
    2. 不要关闭卷曲手柄。重复使用它。

    作为当前的解决方法,您可以使用更高的memroy_limit 运行 php 脚本

     $ php -d memory_limit=1G /path/to/script
    

    1G 表示 1 GB。

    【讨论】:

    • 谢谢。绝对是在正确的方向。我确实尝试删除CUROPT_RETURNTRANSFER,但在我发出的最后一个 curl 请求中,我需要离开它,所以我仍然遇到内存问题。无论如何,请参阅下面的答案。
    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 2011-02-05
    • 1970-01-01
    • 2016-07-28
    相关资源
    最近更新 更多