Php pg_free_result()是否必要,即使结果超出范围?
PHP文档中有关于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
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答案中作为注释发布的测试来看,它似乎也适用。但这只是一个测试,不是官方记录的行为。