是否必须使用pg_free_result(),即使结果超出范围?

时间:2013-05-14 22:53:39

标签: php postgresql memory-leaks

PHP文档可以说pg_free_result()

  

只有在脚本期间消耗内存时才需要调用此函数   执行是个问题。否则,所有结果存储器都将是   脚本结束时自动释放。

http://www.php.net/manual/en/function.pg-free-result.php

我会(或许天真地)期望调用pg_query()时返回的资源在超出范围时被垃圾收集。

在这样的假设函数中:

function selectSomething ()
{
    $res = pg_query("SELECT blah FROM sometable");
    // do something with $res
    pg_free_result($res);   // required or not?
}

是否真的有必要在最后致电pg_free_result()

换句话说,如果我将此函数调用1000次,它会占用内存来存储所有1000个结果吗?

编辑:我说的是典型案例,即pg_connect()而不是pg_pconnect()

2 个答案:

答案 0 :(得分:1)

正如Elias Van Ootegem正确地指出你几乎肯定使用持久连接。在查询后使用持久连接,结果必须在内存中继续,因为您可能希望从中收集更多数据(例如最后一个错误)。

所以归结为良好的做法。如果您在具有2M可用内存的环境中运行,并且您的脚本有时可以达到0.1M内存,那么上限是20个并发连接调用该脚本。之后,进一步的Web请求将排队或丢弃。它不需要天才就能意识到这可能对DDoS攻击有多么脆弱。

然后,最佳做法是在完成后立即清空内存。这适用于任何编程或脚本。当系统受到压力并且需求很高时,可以在整个内存范围内提供服务的请求越多越好。如果您可以降低脚本的最大内存占用量,则可以增加可以合理地尝试调用它的并发连接数,从而增加脚本可以处理的负载。

做事的理想方式是尽快释放资源。仅仅因为我们不这样做,而且在测试过程中一切似乎都有效。没有理由不这样做。

答案 1 :(得分:0)

以下是我的测试结果:

(之前/之后)

with:631288/631384

没有:631288/631640

您可以使用以下代码自行运行测试:

<?php
class test {
    private static $tests = 5000;

    public function __construct() {
        $dbconn = pg_connect("host=### dbname=### user=### password=###")
            or die('Could not connect: ' . pg_last_error());

        self::test(self::$tests, true);
        self::test(self::$tests, false);
    }

    private function test($times, $with) {
        echo ($with ? "with:<br />\n" : "without:<br />\n") . memory_get_usage() ."<br />\n";

        for($i = 0; $i < $times; $i++) {
            $res = pg_query("SELECT * FROM chowder");

            if($with) {
                pg_free_result($res);
            }
        }

        echo memory_get_usage() ."<br /><br />\n\n";
    }

}

$test = new test();