为什么 PHP Doctine 的 free() 不起作用?

2024-08-15php开发问题
0

本文介绍了为什么 PHP Doctine 的 free() 不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

这是给你们任何 Doctrine 用户的.我有一个 PHP CLI 守护进程,它每 n 秒检查一次表以查找尚未处理的条目.它基本上是一个FIFO.无论如何,我总是超过分配给 PHP 的内存,因为 Doctrine 并没有释放它的资源.为了解决这个问题,它免费提供了查询对象.我似乎无法让它工作.代码如下:

This is one is for any of you Doctrine users out there. I have a PHP CLI daemon process that checks a table every n seconds to find entries that haven't been processed. It's basically a FIFO. Anyways, I always exceed the memory allocated to PHP becuase Doctrine does not free it's resources. To combat this problem it provides free for the query object. I can't seem to make it work though. Here's the code:

 22     print "You are using " . (memory_get_usage() / 1024). "
";
 23     $query = Doctrine_Query::create()
 24                 ->from('SubmissionQueue s')
 25                 ->where('s.time_acted_on IS NULL')
 26                 ->orderby('s.time_queued')
 27                 ->limit(1)
 28                 ->execute();
 29     print $query[0]->time_queued . "
";
 30     $query->free();

任何想法我做错了什么?

Any ideas what I am doing wrong?

我使用的是 1.0.3

I am using 1.0.3

我已经尝试了以下所有建议.我对 unset() 非常有希望,因为我在找到 free() 之前就已经在里面了.

I have tried all of the below suggestions. I was very hopeful for unset() as I had it in there before I found free().

这里有更多可能有助于任何帮助的代码.在您质疑连接的打开和关闭之前,它将是生成子进程的守护进程,并且根据我的经验,连接必须是唯一的.

Here is more of the code to possibly aid in any help. Before you question the opening and closing of the connection it will be daemon process that spawns children and from I have experienced the connection has to be unique.

  1 <?php
  2
  3 require_once('/usr/local/lib/php/Doctrine/lib/Doctrine.php');
  4
  5 spl_autoload_register(array('Doctrine', 'autoload'));
  6
  7 $manager = Doctrine_Manager::getInstance();
  8 $manager->setAttribute('model_loading','conservative');
  9 Doctrine::loadModels('lib/model/master');
 10
 11 while(1){
 12     print "You are using " . intval(memory_get_usage() / 1024) . "
";
 13     $manager->connection('********************************************','master');
 14     $query = Doctrine_Query::create()
 15                 ->from('SubmissionQueue s')
 16                 ->where('s.time_acted_on IS NULL')
 17                 ->orderby('s.time_queued')
 18                 ->limit(1)
 19                 ->execute();
 20     print "[" . $query[0]->time_queued . "]
";
 21     $query->free();
 22     unset($query);
 23     $query = null;
 24     $manager->closeConnection(Doctrine_Manager::getInstance()->getConnection('master'));
 25     sleep(5);
 26 }
 27

一些示例输出:

You are using 14949KB
[2008-11-17 13:59:00]
You are using 14978KB
[2008-11-17 13:59:00]
You are using 15007KB
[2008-11-17 13:59:00]
You are using 15035KB
[2008-11-17 13:59:00]
You are using 15064KB
[2008-11-17 13:59:00]
You are using 15093KB
[2008-11-17 13:59:00]
You are using 15121KB
[2008-11-17 13:59:00]
You are using 15150KB
[2008-11-17 13:59:00]
You are using 15179KB
[2008-11-17 13:59:00]
You are using 15207KB
[2008-11-17 13:59:00]
You are using 15236KB
[2008-11-17 13:59:00]
You are using 15265KB
[2008-11-17 13:59:00]
You are using 15293KB
[2008-11-17 13:59:00]
You are using 15322KB

推荐答案

问题是,free() 并没有从内存中删除 Doctrine 对象,只是消除了这些对象上的循环引用,使垃圾收集器可以清理这些对象.请参阅23.6 自由对象教义手册:

The problem is, that free() does not remove the Doctrine objects from memory but just eliminates the circular references on those objects, making it possible for the garbage collector to cleanup those objects. Please see 23.6 Free Objects in the Doctrine manual:

从 5.2.5 版本开始,PHP 不能垃圾收集对象图有循环引用,例如家长有一个 Child 的引用,它有一个参考家长.由于许多教义模型对象有这样的关系,PHP不会释放他们的即使对象用完也能记忆范围.

As of version 5.2.5, PHP is not able to garbage collect object graphs that have circular references, e.g. Parent has a reference to Child which has a reference to Parent. Since many doctrine model objects have such relations, PHP will not free their memory even when the objects go out of scope.

对于大多数 PHP 应用程序,这问题影响不大,因为 PHP 脚本往往是昙花一现.寿命更长的脚本,例如批量数据导入器和出口商,可能会耗尽内存除非你手动打破循环参考链.教义提供了一个Doctrine_Record 上的 free() 函数,Doctrine_Collection 和Doctrine_Query 消除了对这些对象的循环引用,将它们释放为垃圾收藏.

For most PHP applications, this problem is of little consequence, since PHP scripts tend to be short-lived. Longer-lived scripts, e.g. bulk data importers and exporters, can run out of memory unless you manually break the circular reference chains. Doctrine provides a free() function on Doctrine_Record, Doctrine_Collection, and Doctrine_Query which eliminates the circular references on those objects, freeing them up for garbage collection.

解决办法应该是unset()使用free()后的$query对象:

The solution should be to unset() the $query object after using free():

$query = Doctrine_Query::create()
            ->from('SubmissionQueue s')
            ->where('s.time_acted_on IS NULL')
            ->orderby('s.time_queued')
            ->limit(1);
$query->execute();
print $query[0]->time_queued . "
";
$query->free();
unset($query); // perhaps $query = null; will also work

这篇关于为什么 PHP Doctine 的 free() 不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

PHP实现DeepL翻译API调用
DeepL的翻译效果还是很强大的,如果我们要用php实现DeepL翻译调用,该怎么办呢?以下是代码示例,希望能够帮到需要的朋友。 在这里需要注意,这个DeepL的账户和api申请比较难,不支持中国大陆申请,需要拥有香港或者海外信用卡才行,没账号的话,目前某宝可以...
2025-08-20 php开发问题
168

PHP通过phpspreadsheet导入Excel日期数据处理方法
PHP通过phpspreadsheet导入Excel日期,导入系统后,全部变为了4开头的几位数字,这是为什么呢?原因很简单,将Excel的时间设置问文本,我们就能看到该日期本来的数值,上图对应的数值为: 要怎么解决呢?进行数据转换就行,这里可以封装方法,或者用第三方的...
2024-10-23 php开发问题
287

mediatemple - 无法使用 codeigniter 发送电子邮件
mediatemple - can#39;t send email using codeigniter(mediatemple - 无法使用 codeigniter 发送电子邮件)...
2024-08-23 php开发问题
11

Laravel Gmail 配置错误
Laravel Gmail Configuration Error(Laravel Gmail 配置错误)...
2024-08-23 php开发问题
16

将 PHPMailer 用于 SMTP 的问题
Problem with using PHPMailer for SMTP(将 PHPMailer 用于 SMTP 的问题)...
2024-08-23 php开发问题
4

关于如何在 GoDaddy 服务器中使用 PHPMailer 设置 SMTP 的问题
Issue on how to setup SMTP using PHPMailer in GoDaddy server(关于如何在 GoDaddy 服务器中使用 PHPMailer 设置 SMTP 的问题)...
2024-08-23 php开发问题
17