Doctrine似乎占用超过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
/***************************************************/
这是在一个测试数据库中,其中包含非常少的数据 - 我查询的项目不包含除此处显示的数据之外的任何数据。
我的系统设置方式是否有问题,或者是Doctrine的标准内存使用情况?
答案 0 :(得分:6)
从我所看到的,你的代码似乎没有错......
作为测试,我已经设置了一个快速示例,其中包含一个非常简单的表(仅限四个字段)。
以下是相关代码:
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)
考虑到表格非常简单,而且我只提取了一行,对我来说似乎“太多”了 - 但这与你得到的结果非常一致,并且与我在其他项目中看到的一致: - (< / p>
如果您只需要显示数据,而不是使用它(即更新/删除/ ...),解决方案可能是不提取复杂对象,而只是一个简单的数组:
$test = Doctrine::getTable('Test')->find(1, Doctrine::HYDRATE_ARRAY);
但是,在这种情况下,它并没有太大的区别,实际上:-(:
string '1,316,424' (length=9)
string '2,107,128' (length=9)
只有40 KB的差异 - 好吧,有更大的物体/更多的线条,它可能仍然是一个好主意......
在Doctrine手册中,有一个名为Improving Performance的页面;也许它可以帮助你,特别是对于这些部分:
哦,顺便说一下:我在PHP 5.3.0上做过这个测试;也许这会对使用的内存量产生影响......
答案 1 :(得分:5)
我同意romanb的回答 - 在使用大型库/框架时,使用OpCode缓存是必须的。
与OpCode缓存相关的示例
我最近采用了Zend Framework的Doctrine用法并且对内存使用感到好奇 - 所以和OP一样,我创建了一个使用类似OPs测试标准的方法,并将其作为一个整体测试运行,看看ZF + Doctrine的峰值是什么内存使用情况。
我得到了以下结果:
没有APC的结果:
10.25 megabytes
RV David
16.5 megabytes
APC的结果:
3 megabytes
RV David
4.25 megabytes
操作码缓存会产生非常显着的差异。
答案 2 :(得分:4)
嗯,这个内存使用来自哪里?正如Pascal MARTIN所指出的那样,阵列水合作用并没有太大的区别,这在逻辑上是因为我们只是在谈论一些记录。
内存消耗来自通过自动加载按需加载的所有类。
如果您没有设置APC,那么是的,您的系统设置方式有问题。甚至不开始测量性能,并期望任何大型PHP库没有APC等操作码缓存的良好结果。除了第一个负载(APC需要首先缓存字节码)之外,它不仅可以加速执行,还可以减少所有页面加载的内存使用量至少50%。
4MB的简单示例真的闻起来像没有APC,否则它真的会有点高。
答案 3 :(得分:4)
在Doctrine Query上使用fetchOne()时要小心。此函数调用不会在SQL
上追加“限制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;
}
答案 4 :(得分:2)
Doctrine在Doctrine_Record,Doctrine_Collection和Doctrine_Query上提供了一个free()函数,它消除了对这些对象的循环引用,将它们释放出来进行垃圾回收。 More info..
使内存使用量少一点您可以尝试使用以下代码:
答案 5 :(得分:1)
我猜大多数内存用于加载Doctrine的类,而不是用于与查询本身相关联的对象。
在Doctrine 1.1中,默认的自动加载行为称为“激进”,即使您在任何特定请求中仅使用一个或两个,它也会加载所有模型类。将该行为设置为“保守”将减少内存使用量。
答案 6 :(得分:0)
我刚刚使用symfony 1.4执行了“daemonized”脚本,并设置以下内容停止了内存占用:
sfConfig::set('sf_debug', false);