2009-08-29 1 views
23

Существует способ получить общую память, используемую PHP (memory_get_usage()), но как получить размер в памяти отдельного объекта?Получение размера в памяти объекта в PHP?

Я, очевидно, не говорю о count(), так как я хочу количество байтов в потенциально сложной структуре данных.

ответ

15

Вы можете вызвать memory_get_usage() до и после выделения вашего класса, как показано в this example from IBM. Вы могли бы даже создать оболочку для этого, возможно, сохраняя результат в переменной-члене самого сложного класса.

EDIT:

Для уточнения части о хранении выделенного объема памяти, вы можете сделать что-то вроде этого:

class MyBigClass 
{ 
    var $allocatedSize; 
    var $allMyOtherStuff; 
} 

function AllocateMyBigClass() 
{ 
    $before = memory_get_usage(); 
    $ret = new MyBigClass; 
    $after = memory_get_usage(); 
    $ret->allocatedSize = ($after - $before); 

    return $ret; 
} 

В любой момент в будущем, вы можете проверить allocatedSize, чтобы увидеть, насколько велики этот объект находился во время выделения. Если вы добавите его после его выделения, однако, allocSize больше не будет точным.

+1

Что делать, если PHP решает освободить память, которая была выделена, только в «неправильное время»? Я действительно не знаю, когда PHP освобождает память (вроде бы «когда нужно», я полагаю), но я предполагаю, что это освобождение может принести некоторые проблемы? Особенно с сборщиком мусора, представленным PHP 5.3 для циклических ссылок? –

+0

Ну да, но в дополнение к тому, что упоминал Паскаль, я хочу, чтобы это можно было найти в разное время, а не только во время распределения. Я хочу найти это много линий по дороге. –

+0

@Pascal: PHP не освобождает память, на которую все еще ссылается объект, активно используемый. Циклические ссылки означают ссылки B и B ссылки A, но ничто иное не ссылается ни на A, ни на B. Таким образом, память не будет освобождена до тех пор, пока программа все равно может ссылаться на нее. –

3

Я не думаю, что это вполне возможно; Я никогда не видел ничего, что позволило бы получить размер объекта в памяти.

Решение для получения довольно грубой идеи может быть связано с сериализацией ваших данных и использованием strlen на этом ... Но это действительно будет чем-то вроде оценки ... Я бы не совсем полагался на что-либо подобное что, на самом деле ...


Даже debug_zval_dump не делает этого: его выводе данных в переменной и RefCount, но не память используется:

$obj = new stdClass(); 
$obj->a = 152; 
$obj->b = 'test'; 

echo '<pre>'; 
debug_zval_dump($obj); 
echo '</pre>'; 

будет только вам:

object(stdClass)#1 (2) refcount(2){ 
    ["a"]=> 
    long(152) refcount(1) 
    ["b"]=> 
    string(4) "test" refcount(1) 
} 
+0

Очень интересно. Мой следующий вопрос состоял в том, чтобы получить информацию о том, почему происходит утечка памяти. Благодаря! –

11

Не имеет смысла пробовать сериализацию объекта и чтение длины строки? Очевидно, что это будет несколько байтов, потому что сериализованная строка имеет s: 'string', поэтому s: '' является дополнительными байтами ... если serialize не может быть таким же, как PHP хранит объекты ???

так, например

$size = strlen(serialize($object)); 

Просто мысли?

Другой грязная, но, возможно, точная мысль:

Предполагая переменный экземпляр класса, который был манипулирует несколько раз, так как конкретизация:

$DB; // database access class for eg. 
$mem = memory_get_usage(); 
$DB_tmp = clone $DB; 
$mem = memory_get_usage() - $mem; 
unset($DB_tmp); 

$ ает может быть точным объемом памяти, выделяемый $ DB ;

+0

** clone ** не работает для меня (я не знаю почему). Он всегда сообщает 100 байт после клонирования объекта. –

1

Поскольку клон (от Prof83's answer) не работает для меня, я пытался сериализации и десериализируются переменную, размер которой я хочу, чтобы измерить:

function getMemoryUsage($var) { 
    $mem = memory_get_usage(); 
    $tmp = unserialize(serialize($var)); 
    // Return the unserialized memory usage 
    return memory_get_usage() - $mem; 
} 

Я думаю, что он сообщает лучшие результаты, по крайней мере, для меня.

+0

вы не использовали переменную '$ tmp' –

0

Если вы просто хотите узнать размер объекта, а не для своего следующего кода, return его в браузере, и вы можете увидеть, сколько сеть передает объект.