İki değişken bellekte aynı ayrılmış alanı paylaşabileceğinden, bir değişkenin tam ayak izini geriye dönük olarak hesaplayamazsınız
Hafızayı iki dizi arasında paylaşmaya çalışalım, ikinci diziyi ayırmanın ilkinin belleğinin yarısına mal olduğunu görüyoruz. Birincisinin ayarını kaldırdığımızda, neredeyse tüm hafıza hala ikincisi tarafından kullanılır.
echo memory_get_usage()."\n"; // <-- 433200
$c=range(1,100);
echo memory_get_usage()."\n"; // <-- 444348 (+11148)
$d=array_slice($c, 1);
echo memory_get_usage()."\n"; // <-- 451040 (+6692)
unset($c);
echo memory_get_usage()."\n"; // <-- 444232 (-6808)
unset($d);
echo memory_get_usage()."\n"; // <-- 433200 (-11032)
Yani ikinci dizinin hafızanın yarısını kullandığı sonucuna varamayız, çünkü ilk diziyi kaldırdığımızda yanlış olur.
PHP'de belleğin nasıl tahsis edildiğini ve hangi amaçla kullanıldığını tam olarak görmek için aşağıdaki makaleyi okumanızı öneririm: PHP dizileri (ve değerleri) gerçekte ne kadar büyük? (İpucu: BÜYÜK!)
Referans Sayma Temelleri PHP belgelerinde ayrıca hafıza kullanımı hakkında birçok bilgi vardır ve referanslar paylaşılan veri segmentine sayar.
Burada açığa çıkan farklı çözümler tahminler için iyidir ancak hiçbiri PHP belleğinin ince yönetimini kaldıramaz.
- yeni tahsis edilen alanın hesaplanması
Bir atamadan sonra yeni tahsis edilen alanı istiyorsanız memory_get_usage()
, tahsisattan önce ve sonra kullanmanız gerekir, çünkü onu bir kopya ile kullanmak size gerçeğin yanlış bir görünümünü verir.
// open output buffer
echo "Result: ";
// call every function once
range(1,1); memory_get_usage();
echo memory_get_usage()."\n";
$c=range(1,100);
echo memory_get_usage()."\n";
Birincinin sonucunu saklamak istiyorsanız memory_get_usage()
, değişkenin daha önce var memory_get_usage()
olması ve bir önceki sefer ve diğer her işlevin de çağrılması gerektiğini unutmayın.
Yukarıdaki örnekte olduğu gibi yankı yapmak istiyorsanız, çıktı arabelleğini açmak için gereken hesaplama belleğini önlemek için çıktı arabelleğiniz zaten açılmış olmalıdır.
- gerekli alanı hesaplamak
Bir değişkenin bir kopyasını depolamak için gerekli alanı hesaplamak için bir işleve güvenmek istiyorsanız, aşağıdaki kod farklı optimizasyonları ele alır:
<?php
function getMemorySize($value) {
// existing variable with integer value so that the next line
// does not add memory consumption when initiating $start variable
$start=1;
$start=memory_get_usage();
// json functions return less bytes consumptions than serialize
$tmp=json_decode(json_encode($value));
return memory_get_usage() - $start;
}
// open the output buffer, and calls the function one first time
echo ".\n";
getMemorySize(NULL);
// test inside a function in order to not care about memory used
// by the addition of the variable name to the $_GLOBAL array
function test() {
// call the function name once
range(1,1);
// we will compare the two values (see comment above about initialization of $start)
$start=1;
$start=memory_get_usage();
$c=range(1,100);
echo memory_get_usage()-$start."\n";
echo getMemorySize($c)."\n";
}
test();
// same result, this works fine.
// 11044
// 11044
Ayrılan bellekteki değişken adının boyutunun önemli olduğuna dikkat edin.
- Kodunuzu kontrol edin !!
Bir değişken, PHP kaynak kodunda kullanılan iç C yapısı tarafından tanımlanan temel bir boyuta sahiptir. Sayılar söz konusu olduğunda bu boyut dalgalanmaz. Dizeler için dizenin uzunluğunu ekler.
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
Değişken adının ilklendirilmesini hesaba katmazsak, bir değişkenin ne kadar kullandığını zaten biliyoruz (sayılar ve dizeler durumunda):
Sayılar durumunda 44 bayt
Dizeler durumunda + 24 bayt
+ dizenin uzunluğu (son NUL karakteri dahil)
(bu sayılar PHP sürümüne göre değişebilir)
Bellek hizalaması nedeniyle 4 bayt katına yuvarlamanız gerekir. Değişken global alandaysa (bir işlevin içinde değilse), 64 bayt daha tahsis edecektir.
Dolayısıyla, bu sayfadaki kodlardan birini kullanmak istiyorsanız, bazı basit test senaryoları (dizeler veya sayılar) kullanan sonucun, bu gönderideki göstergelerin her birini ($ _GLOBAL dizisi, ilk işlev çağrısı, çıktı tamponu, ...)