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

Php pg_free_result()是否必要,即使结果超出范围?,php,postgresql,memory-leaks,Php,Postgresql,Memory Leaks,PHP文档中有关于pg\u free\u result() 仅当脚本执行期间内存消耗时,才需要调用此函数 执行是个问题。否则,所有结果内存将被删除 脚本结束时自动释放 我可能(天真地)期望调用pg_query()返回的资源在超出范围时被垃圾收集 在这样的假设函数中: function selectSomething () { $res = pg_query("SELECT blah FROM sometable"); // do something with $res

PHP文档中有关于
pg\u free\u result()

仅当脚本执行期间内存消耗时,才需要调用此函数 执行是个问题。否则,所有结果内存将被删除 脚本结束时自动释放

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

在这样的假设函数中:

function selectSomething ()
{
    $res = pg_query("SELECT blah FROM sometable");
    // do something with $res
    pg_free_result($res);   // required or not?
}
是否真的需要在最后调用
pg\u free\u result()

换句话说,如果我调用这个函数1000次,它会消耗内存来存储所有1000个结果吗


编辑:我说的是典型案例,即
pg\u connect()
而不是
pg\u pconnect()

以下是我的测试结果:

(之前/之后)

随附: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();

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

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

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


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

视情况而定,您是在强制建立新的pg连接,还是该连接持续存在?如果您使用的是持久连接。但是为什么不分析脚本呢。编写一个小测试用例并检查内存使用情况。如果它一直增加到脚本结束,请添加
pg_free_result
,然后再次运行它…这是一个更一般的问题,无论连接类型如何。我知道我可以写一个测试,但是文档太模糊让我很困扰。一次性测试只会回答我关于一个特定平台和版本(PHP和/或libpq)的问题。我对问题进行了编辑,以说明我所说的是
pg_connect()
。我无法为问题中提到的用例复制您的结果。看看这里:顺便说一下,您的测试通过向$memory\u usage添加键和值直接影响内存使用。去掉这些,你会得到相同的带/不带结果(加上减去两个字节)。我已经更新了我的测试和结果。我在Elias的回答中对此进行了评论,但该答案已随评论一起删除。总而言之:不,这绝对不是持久的联系。在pg_查询中不使用$conn参数,只是隐式地使用由
pg_connect()
(或
pg_pconnect()
)打开的最后一个连接。持久连接是完全不同的。除此之外,它们将在HTTP请求之间保持锁和事务的活动状态(如果使用mod_php),这几乎总是不需要的。我们使用PgBouncer作为连接池。至于最佳实践,PHP使用垃圾收集,这通常不需要显式释放()资源。当它们变得不可访问时(即,当它们超出范围时),它们将被标记为垃圾收集。垃圾收集语言的最佳实践是让GC完成它的任务。问题是,这是否也适用于PG result resources,它确实有一个free()函数,从我在Joel答案中作为注释发布的测试来看,它似乎也适用。但这只是一个测试,不是官方记录的行为。