2009-09-11 41 views
10

主義出現了4MB的內存是採取很好地執行一個單一的,簡單的查詢:主義查詢內存使用

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 

/***************************************************/ 

這是一個試驗數據庫上,在它的數據非常少 - 我是項目查詢不包含除此處顯示的內容之外的任何數據。

有沒有可能是我有系統設置的方式有問題,或者這是標準的內存使用原則?

回答

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手冊中,有一個頁面叫做Improving Performance;也許它可以幫助你,特別是對這些部分:


哦,順便說一句:我做這個測試的PHP 5.3.0;也許這可能會影響內存使用量...

+0

這讓我很擔心,因爲我正在將Doctrine融入到我的框架中。 – 2009-09-11 19:34:55

+0

在擔心太多之前,您可能需要做更多的測試,包括更大的表格,更多的數據以及所有這些 - 以查看內存增加是否是線性的。 ;;順便說一句:我已經看到基於Zend Framework和Symfony的項目中使用的學說,這從來沒有成爲一個問題... – 2009-09-11 19:38:26

+0

帕斯卡爾馬丁:也許這些網站你知道沒有重載?我想知道是否有任何主要網站正在使用Doctrine。 – Fragsworth 2009-09-11 21:36:13

4

那麼,這種內存使用來自哪裏呢?正如Pascal MARTIN指出的那樣,陣列補水不會產生很大的差異,這是合乎邏輯的,因爲我們只在這裏討論幾條記錄。

內存消耗來自所有通過自動加載按需加載的類。

如果您沒有設置APC,那麼是的,您的系統設置方式有問題。甚至不用像APC那樣的操作碼緩存,就可以開始衡量性能並期待任何大型php庫的良好結果。它不僅會加快執行速度,還會減少所有頁面負載(至少第一個APC需要首先緩存字節碼)除外的內存佔用至少50%。

而你的簡單例子中的4MB確實聞起來像沒有APC,否則它確實有點高。

5

我同意romanb的答案 - 使用OpCode緩存是使用大型庫/框架時的必然要求。

我最近通過的原則使用與Zend框架,並很好奇內存使用相關指令緩存的一個例子 - 等等之類的OP,我創建使用類似的標準到OPS測試的方法和將其作爲整體測試來查看ZF + Doctrine的峯值內存使用情況。

我得到以下結果:

的結果,而不APC:

10.25 megabytes 
RV David 
16.5 megabytes 

結果與APC:

3 megabytes 
RV David 
4.25 megabytes 

指令緩存讓人十分顯著差異。

2

Doctrine在Doctrine_Record,Doctrine_Collection和Doctrine_Query上提供了一個免費()函數,它消除了這些對象的循環引用,釋放它們以進行垃圾回收。 More info..

爲了使內存的使用情況有點少,你可以嘗試使用如下因素代碼:

  • $ record->免費(真) - 上都將做深騰出的,電話免費()關係太
  • $收藏 - >免費() - 這將釋放所有集合引用
  • Doctrine_Manager ::連接() - >清理()/清除() - 清除連接(和刪除標識映射條目)
  • $ query-> free()
1

我猜想大部分內存用於加載Doctrine的類,實際上並不適用於與查詢本身相關的對象。

  • 您使用的是哪個版本的Doctrine?
  • 您是否使用自動裝載機?

在Doctrine 1.1中,默認的自動加載行爲被稱爲'積極',這意味着即使您只對任何特定請求使用一個或兩個模型類,它也會加載所有模型類。將該行爲設置爲「保守」會減少內存使用量。

0

我剛纔沒有「進程化」在symfony 1.4和設置下面的腳本停止內存佔用:)原則上查詢

sfConfig::set('sf_debug', false); 
+0

如果您使用doctrine + symfony,但不會幫助,如果你只是使用Doctrine。 – 2011-01-02 19:49:02

+0

同意Ikon,在symfony中探測器gobals ram。所以:'sfConfig :: set('sf_debug',false);'** BEFORE **數據庫連接將會非常緩慢,如果像我一樣,將大表轉儲到csv。你可能想在* frontend_dev.php *或類似的(第三參數)中執行此操作。 – 2011-06-01 23:14:23

4

注意與fetchOne(。此函數調用不會追加「限制1」上的SQL

如果你只是需要從數據庫得到一個記錄,確保:

$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; 
}