Php 条令查询内存使用

Php 条令查询内存使用,php,doctrine,memory-management,Php,Doctrine,Memory Management,条令似乎占用了超过4MB的RAM来执行一个简单的查询: print memory_get_peak_usage()." <br>\n"; $q = Doctrine_Query::create() ->from('Directories d') ->where('d.DIRECTORY_ID = ?', 5); $dir = $q->fetchOne(); print $dir['name']." ".$dir['description']."&l

条令似乎占用了超过4MB的RAM来执行一个简单的查询:

print memory_get_peak_usage()." <br>\n";
$q = Doctrine_Query::create()
    ->from('Directories d')
    ->where('d.DIRECTORY_ID = ?', 5);

$dir = $q->fetchOne();
print $dir['name']." ".$dir['description']."<br>\n";

print memory_get_peak_usage()." <br>\n";

/***************  OUTPUT:  **************************

6393616
testname testdescription
10999648

/***************************************************/
print memory\u get\u peak\u usage()。“
\n”; $q=条令查询::创建() ->从('d'目录) ->其中('d.DIRECTORY_ID=?',5); $dir=$q->fetchOne(); 打印$dir['name']。“.$dir['description']。”
\n”; 打印内存获取峰值使用率()。“
\n”; /***************输出:************************** 6393616 testname testdescription 10999648 /***************************************************/
这是在一个测试数据库上,其中只有很少的数据-我查询的项目不包含除此处显示的数据以外的任何数据


我设置系统的方式是否有潜在的问题,或者这是条令的标准内存使用方式?

从我看来,您的代码似乎没有错


作为测试,我设置了一个快速示例,其中有一个非常简单的表(只有四个字段)

以下是相关代码:

var_dump(number_format(memory_get_peak_usage()));

$test = Doctrine::getTable('Test')->find(1);

var_dump(number_format(memory_get_peak_usage()));
这样做时,我有这样的输出:

string '1,316,088' (length=9)
string '2,148,760' (length=9)
考虑到表格非常简单,而且我只提取了一行,对我来说似乎也“很多”——但这与您得到的以及我在其他项目中看到的非常一致:-(


如果您只需要显示数据,而不需要使用数据(即更新/删除/…),解决方案可能是不获取复杂对象,而只获取简单数组:

$test = Doctrine::getTable('Test')->find(1, Doctrine::HYDRATE_ARRAY);
但是,在这种情况下,实际上没有多大区别

只有40KB的差异——好吧,对于更大的对象/更多的线,这可能仍然是一个好主意


在条令手册中,有一个页面名为;也许它可以帮助您,尤其是以下章节:



哦,顺便说一句:我在PHP5.3.0上做了这个测试;也许这会对使用的内存量产生影响…

那么,内存的使用是从哪里来的呢?正如Pascal MARTIN指出的,数组水合作用并没有太大的区别,这是合乎逻辑的,因为我们这里只讨论了一些记录

内存消耗来自通过自动加载按需加载的所有类

如果您没有设置APC,那么是的,您的系统设置方式有问题。对于没有操作码缓存(如APC)的大型php库,甚至不要开始测量性能,也不要期望有好的结果。这不仅会加快执行速度,而且会在除fir之外的所有页面负载上减少至少50%的内存使用st one(APC需要首先缓存字节码)


4MB和您的简单示例闻起来真的像没有APC,否则它会真的有点高。

我同意romanb的答案-在使用大型libs/框架时,使用操作码缓存是绝对必须的

与操作码缓存相关的示例

我最近在Zend框架中采用了条令使用,并且对内存使用感到好奇——因此像OP一样,我使用与OPs测试类似的标准创建了一个方法,并将其作为一个整体测试运行,以查看ZF+条令的内存使用峰值

我得到了以下结果:

无APC的结果:

10.25 megabytes
RV David
16.5 megabytes
APC的结果:

3 megabytes
RV David
4.25 megabytes
操作码缓存有很大的不同。

条令在条令记录、条令收集和条令查询上提供了一个free()函数,它消除了这些对象上的循环引用,将它们释放出来进行垃圾收集。

要稍微减少内存使用,您可以尝试使用以下代码:

  • $record->free(true)–将对所有关系执行深度释放,调用free()
  • $collection->free()–这将释放所有集合引用
  • Doctrine_Manager::connection()->clean()/clear()–清理连接(并删除标识映射项)
  • $query->free()

我猜大部分内存都被用来加载Doctrine的类,而不是用于与查询本身关联的对象

  • 您使用的是哪种版本的学说
  • 你在用自动装弹机吗
在原则1.1中,默认的自动加载行为称为“侵略性”,这意味着即使您在任何特定请求中只使用一个或两个模型类,它也会加载所有模型类。将该行为设置为“保守”将减少内存使用。

我刚刚做了“daemonized”使用symfony 1.4编写脚本,并设置以下选项可停止内存占用:

sfConfig::set('sf_debug', false);
注意在条令查询中使用fetchOne()。此函数调用不会在SQL上附加“Limit 1”

如果您只需要从DB获取一条记录,请确保:

$q->limit(1)->fetchOne() 
大表上的内存使用率大大降低

您可以看到fetchOne()将首先作为集合从数据库中获取,然后返回第一个元素

public function fetchOne($params = array(), $hydrationMode = null)
{
    $collection = $this->execute($params, $hydrationMode);

    if (is_scalar($collection)) {
        return $collection;
    }

    if (count($collection) === 0) {
        return false;
    }

    if ($collection instanceof Doctrine_Collection) {
        return $collection->getFirst();
    } else if (is_array($collection)) {
        return array_shift($collection);
    }

    return false;
}

这让我担心,因为我正在将条令集成到我的框架中。在担心太多之前,你可能想做更多的测试,使用更大的表、更多的数据,以及所有这些——看看内存增加是否是线性的。;;顺便说一句:我在基于Zend framework和Symfony的项目中看到条令的使用,这从来都不是问题……Pascal MARTIN:也许你知道的这些站点没有重载?我想知道是否有任何主要站点正在使用Doctrine。我通常将新项目锁定为16MB的内存限制。除了一个例外,我从来没有用Doctrine耗尽过该限制。此外,当Doctrine被禁用时,会启动大量内部引用变量和单例第一次使用。1.2文档的链接现在可以在这里找到,如果您使用的是条令+symfony,这很好,但如果您只是使用条令,则不会有帮助。同意Ikon的意见,在symfony中使用分析器gobals ram。因此:
sfConfig::set('sf_debug',false)
在建立数据库连接之前,如果您像我一样将大型表转储到csv,那么这将非常有帮助。您可以在frontend_dev.php或
public function fetchOne($params = array(), $hydrationMode = null)
{
    $collection = $this->execute($params, $hydrationMode);

    if (is_scalar($collection)) {
        return $collection;
    }

    if (count($collection) === 0) {
        return false;
    }

    if ($collection instanceof Doctrine_Collection) {
        return $collection->getFirst();
    } else if (is_array($collection)) {
        return array_shift($collection);
    }

    return false;
}