为什么PHP Doctine的免费()不起作用? [英] Why is PHP Doctine's free() not working?

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

问题描述

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

  22打印您正在使用。 (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();

任何想法我做错了什么?



<编辑:我使用1.0.3



编辑:我已经尝试了以下所有建议。我非常希望 unset(),因为我发现 free()



这里有更多的代码可能有助于任何帮助。在您询问连接的开启和关闭之前,将产生子进程的守护程序进程,从我经历的连接必须是唯一的。

  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(1){
12打印您正在使用。 intval(memory_get_usage()/ 1024)。 \\\
;
13 $ manager-> connection('*************************************** *******','主');
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打印[。 $ query [0] - > time_queued。 ] \\\
;
21 $ query-> free();
22 unset($ query);
23 $ query = null;
24 $ manager-> closeConnection(Doctrine_Manager :: getInstance() - > getConnection('master'));
25睡眠(5);
26}
27

某些示例输出:

 您正在使用14949KB 
[2008-11-17 13:59:00]
您正在使用14978KB
[2008-11-17 13:59:00]
您正在使用15007KB
[2008-11-17 13:59:00]
您正在使用15035KB
[2008 -11-17 13:59:00]
您正在使用15064KB
[2008-11-17 13:59:00]
您正在使用15093KB
[2008-11 -17 13:59:00]
您正在使用15121KB
[2008-11-17 13:59:00]
您正在使用15150KB
[2008-11-17 13:59:00]
您正在使用15179KB
[2008-11-17 13:59:00]
您正在使用15207KB
[2008-11-17 13: 59:00]
您正在使用15236KB
[2008-11-17 13:59:00]
您正在使用15265KB
[2008-11-17 13:59: 00]
您正在使用15293KB
[2008-11-17 13:59:00]
您正在使用15322KB


解决方案

问题是, free()不会删除Doctrine对象从记忆,但只是消除对这些对象的循环引用,使得垃圾收集器可以清理这些对象。请参阅 23.6免费对象 教义手册




从版本5.2.5起,PHP不能
垃圾收集
有循环引用的对象图,例如父
引用了一个对Parent的
引用的Child。由于许多
原则模型对象具有这样的
关系,因此即使对象从
范围出来,PHP也不会释放其
内存。



对于大多数PHP应用程序,这个
问题没有什么影响,
,因为PHP脚本往往是
短暂的。更长寿的脚本,
,例如批量数据导入器和
出口商,可以用尽内存
,除非您手动中断循环
引用链。 Doctrine在Doctrine_Record,
Doctrine_Collection和
Doctrine_Query上提供
free()函数,消除了对这些对象的
循环引用,
释放垃圾
收集。


解决方案应该是 unset() code> $ query 对象使用 free()



<$ p $ ('SubmissionQueue s')
- >其中('s.time_acted_on IS NULL')$ b($ s code)$ query = Doctrine_Query :: create()
- $ b - > orderby('s.time_queued')
- > limit(1);
$ query-> execute();
print $ query [0] - > time_queued。 \\\
;
$ query-> free();
unset($ query); // may $ query = null;也将工作


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). "\n";
 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 . "\n";
 30     $query->free();

Any ideas what I am doing wrong?

EDIT: I am using 1.0.3

EDIT: 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) . "\n";
 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 . "]\n";
 21     $query->free();
 22     unset($query);
 23     $query = null;
 24     $manager->closeConnection(Doctrine_Manager::getInstance()->getConnection('master'));
 25     sleep(5);
 26 }
 27

Some sample output:

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

解决方案

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:

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.

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.

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 . "\n";
$query->free();
unset($query); // perhaps $query = null; will also work

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆