10

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 的标准内存使用?

4

7 回答 7

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)

考虑到表格真的很简单,而且我只取一行,对我来说似乎也“很多”——但这与你得到的以及我在其他项目中看到的完全一致:-(


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

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

但是,在这种情况下,实际上并没有太大区别:-(:

string '1,316,424' (length=9)
string '2,107,128' (length=9)

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


在 Doctrine 手册中,有一个页面叫做Improvement Performance;也许它可以帮助你,特别是对于这些部分:


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

于 2009-09-11T19:25:05.103 回答
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

操作码缓存有很大的不同。

于 2009-10-10T05:18:33.777 回答
4

那么,这种内存使用量是从哪里来的呢?正如 Pascal MARTIN 所指出的,阵列水合并没有产生很大的不同,这是合乎逻辑的,因为我们在这里只讨论了几条记录。

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

如果您没有设置 APC,那么是的,您的系统设置方式有问题。甚至不要开始测量性能并期望在没有像 APC 这样的操作码缓存的任何大型 php 库中获得良好的结果。除了第一个页面加载(APC 需要首先缓存字节码)之外,它不仅会加快执行速度,而且还会将所有页面加载的内存使用量减少至少 50%。

并且 4MB 与你的简单示例真的闻起来像没有 APC,否则它真的有点高。

于 2009-09-28T09:35:56.073 回答
4

在 Doctrine Query 上使用 fetchOne() 时要小心。此函数调用不会在 SQL 上附加“限制 1”

如果您只需要从数据库中获取一条记录,请确保:

$q->limit(1)->fetchOne() 

大表上的内存使用量大幅下降。

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

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;
}
于 2012-05-16T10:07:08.170 回答
2

Doctrine 在 Doctrine_Record、Doctrine_Collection 和 Doctrine_Query 上提供了一个 free() 函数,它消除了对这些对象的循环引用,将它们释放用于垃圾回收。 更多信息..

为了减少内存使用量,您可以尝试使用以下代码:

  • $record->free(true) – 将做深度释放,在所有关系上调用 free()
  • $collection->free() - 这将释放所有集合引用
  • Doctrine_Manager::connection()->clean()/clear() – 清理连接(并删除身份映射条目)
  • $查询->免费()
于 2010-02-21T14:24:45.890 回答
1

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

  • 您使用的是哪个版本的教义?
  • 你在使用自动加载器吗?

在 Doctrine 1.1 中,默认的自动加载行为被称为“积极”,这意味着它会加载所有模型类,即使您在任何特定请求上只使用一个或两个。将该行为设置为“保守”会减少内存使用量。

于 2010-03-07T16:22:41.960 回答
0

我刚刚使用 symfony 1.4 做了“守护进程”脚本,并设置以下内容停止了内存占用:

sfConfig::set('sf_debug', false);
于 2010-04-20T13:43:17.817 回答