2009年1月7日 星期三

測試PHP中物件屬性的使用記憶體

定義:

class c5 {
var $a1 = 1;
var $a2 = 2;
var $a3 = 3;
var $a4 = 4;
var $a5 = 5;
var $a6 = 6;
var $a7 = 7;
var $a8 = 8;
var $a9 = 9;
var $a10 = 10;
}
class c6 {
var $a1 = array(
'a1'=>1,
'a1'=>2,
'a1'=>3,
'a1'=>4,
'a1'=>5,
'a1'=>6,
'a1'=>7,
'a1'=>8,
'a1'=>9,
'a1'=>10);
}

new 10000個結果:
C5: 7297.2/7297.3 (kb)
C6: 2766.0/2766.1 (kb)

結論:
初始物件屬性佔用的記憶體與數量有關, 但與內容大小無關.
猜測PHP使用 copy on write 技術, 若內容沒有改變,
所有new出來的物件該屬性會指向相同的位址,
並不會額外配置記憶體,
除非後來修改該內容會另外複製一份記憶體.

此結論推翻先前的建議,
亦即若ORM中的Model屬性永遠不變, 例如(一對多的結構設定),
則額外的記憶體成本很低.

測試PHP中array與物件的使用記憶體

定義:

class c1 {
}

class c2 {
function f1() {}
function f2() {}
function f3() {}
function f4() {}
function f5() {}
}

class c3 {
var $a1;
}

結果:

100 1000 10000
-------------------------------------------------------------------
cl: 85.6/85.8 250.8/250.9 2288.0/2288.1
c2: 85.6/85.8 250.8/250.9 2288.0/2288.1
c3: 89.3/89.4 296.7/296.8 2755.8/2755.9
array: 83.0/85.5 227.1/227.2 1693.4/1693.4

*數字: memory_get_usage/memory_get_peak_usage (kb)

結論:
1. 物件比Array佔用的記憶體多.
2. 物件內宣告method不會佔用記憶體(應該只是一個vtable結構).
3. 物件內宣告屬性會佔用記憶體.

所以在開發ORM時, 應該儘量避免宣告屬性,
把必要屬性包裝在method中, 必要時才呼叫method讀取,
在提取大量Model時可有效降低記憶體的使用量.

測試PHP中Mysql的使用記憶體


結果:
100 1000 10000
---------------------------------------------------------------------
MYSQL_NUM: 187.4/187.5 1294.8/1294.9 12394.0/12394.1
MYSQL_ASSOC: 188.2/188.2 1302.7/1302.7 12472.2/12472.2
MYSQL_BOTH: 250.6/250.6 1927.6/1927.6 18722.1/18722.2
MYSQL_OBJ: 191.0/191.1 1326.6/1326.6 13067.5/13067.5

*數字: memory_get_usage/memory_get_peak_usage (kb)

結論:
mysql_fetch_object與mysql_fetch_array所佔用的記憶體差不多.