Как определить объем памяти (размер) переменной?


есть ли функция в PHP (или расширение PHP), чтобы узнать, сколько памяти использует данная переменная? sizeof просто говорит Мне количество элементов / свойств.

memory_get_usage помогает в том, что он дает мне размер памяти, используемый весь сценарий. Есть ли способ сделать это для одной переменной?

обратите внимание, что это на машине разработки, поэтому загрузка расширений или инструментов отладки возможна.

11 95

11 ответов:

вам, вероятно, нужен профилировщик памяти. Я собрал информацию для этого, но я скопировал некоторые важные вещи, которые могут помочь вам также.

как вы, наверное, знаете, Xdebug сбросил поддержку профилирования памяти с 2.* версия. Пожалуйста, найдите строку "удаленные функции" здесь:http://www.xdebug.org/updates.php

удалены функции

удалена поддержка профилирования памяти, что не работает должным образом.

Другие Параметры Профилировщика

php-memory-profiler

https://github.com/arnaud-lb/php-memory-profiler. Вот что я сделал на своем сервере Ubuntu, чтобы включить его:

sudo apt-get install libjudy-dev libjudydebian1
sudo pecl install memprof
echo "extension=memprof.so" > /etc/php5/mods-available/memprof.ini
sudo php5enmod memprof
service apache2 restart

а потом в мой код:

<?php
memprof_enable();
// do your stuff
memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));

открыть С KCachegrind

использование Google gperftools (рекомендуется!)

прежде всего установите Google gperftools загрузив последний пакет здесь:https://code.google.com/p/gperftools/

потом как всегда:

sudo apt-get update
sudo apt-get install libunwind-dev -y
./configure
make
make install

теперь в вашем коде:

memprof_enable();

// do your magic

memprof_dump_pprof(fopen("/tmp/profile.heap", "w"));

затем откройте терминал и запустите:

pprof --web /tmp/profile.heap

обновлением инструментария RPM при обновлении создать новое окно в существующей сессии браузера, то, как показано ниже:

PHP memory profiling with memprof and gperftools

Xhprof + Xhgui (лучший на мой взгляд для профилирования как процессора, так и памяти)

С Xhprof и Xhgui вы можете профилировать использование процессора, а также или просто использование памяти, если это ваша проблема на данный момент. Это очень полное решение, оно дает вам полный контроль, и журналы могут быть записаны как на mongo, так и в файловой системе.

для более подробной информации посмотреть здесь.

Черный огонь

Blackfire-это PHP-профилировщик от SensioLabs, ребята Symfony2 https://blackfire.io/

если вы используете puphpet чтобы настроить виртуальную машину, вы будете рады узнать, что она поддерживается ; -)

Xdebug и трассировка использования памяти

XDEBUG2 - это расширение для PHP. Xdebug позволяет регистрировать все вызовы функций, включая параметры и возвращаемые значения в файл в различных форматах.Существует три выходных формата. Один подразумевается как человек читаемый след, другой-больше подходит для компьютерных программ, так как его легче разобрать, а последний использует HTML для форматирования след. Вы можете переключаться между двумя различными форматами с настройкой. Примером может быть здесь

forp

forp простой, неинтрузивный, ориентированный на производство, PHP-профилировщик. Некоторые из особенностей:

  • измерение времени и выделенной памяти для каждого функция

  • загрузка ЦП

  • номер файла и строки вызова функции

  • вывод в формате трассировки событий Google

  • заголовок функции

  • группирование функций

  • псевдонимы функций (полезно для анонимных функций)

DBG

DBG это a полнофункциональный PHP отладчик, интерактивный инструмент, который поможет вам отлаживать PHP скрипты. Он работает на производственном и / или веб-сервере разработки и позволяет отлаживать сценарии локально или удаленно, из IDE или консоли, а его функции:

  • Удаленная и локальная отладка

  • явная и неявная активация

  • стек вызовов, включая вызовы функций, динамические и статические вызовы методов, с их параметры

  • навигация по стеку вызовов с возможностью оценки переменных в соответствующих (вложенных) местах

  • шаг/шаг/шаг/выполнение до курсора функции

  • условные точки останова

  • глобальные точки останова

  • Регистрация ошибок и предупреждений

  • множественные одновременные встречи для параллели отладка

  • поддержка интерфейсов GUI и CLI

  • IPv6 и IPv4 сети поддерживаются

  • все данные, передаваемые отладчиком, могут быть дополнительно защищены SSL

нет прямого способа получить использование памяти одной переменной, но, как предложил Гордон, вы можете использовать memory_get_usage. Это вернет общий объем выделенной памяти, поэтому вы можете использовать обходной путь и измерять использование до и после, чтобы получить использование одной переменной. Это немного hacky, но он должен работать.

$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;

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

вы можете фактически превратить это в функцию, создав копию переменной внутри функции и измерив используемую память. Не проверял это, но в принципе, я не вижу в этом ничего плохого:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $tmp = unserialize(serialize($var));
    return memory_get_usage() - $start_memory;
}

нет, нет. Но вы можете serialize($var) и проверяем strlen результата для аппроксимации.

в ответ на тату Ульманен отвечает:

отметим, что $start_memory сам займет память (PHP_INT_SIZE * 8).

таким образом, вся функция должна стать:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $var = unserialize(serialize($var));
    return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8;
}

Извините, что добавляю это в качестве дополнительного ответа, но я пока не могу прокомментировать ответ.

обновление: *8 не определено. Это может зависеть, по-видимому, от версии php и, возможно, от 64/32 бит.

посмотреть:

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

вы также может взгляните на расширение PECL Memtrack, хотя документация немного не хватает, если не сказать, практически не существует.

вы можете выбрать для вычисления разницы памяти на обратном вызове возвращаемого значения. Это более элегантное решение, доступное в PHP 5.3+.

function calculateFootprint($callback) {
    $startMemory = memory_get_usage();
    $result = call_user_func($callback);
    return memory_get_usage() - $startMemory;
}

$memoryFootprint = calculateFootprint(
    function() {
        return range(1, 1000000);
    }
);

echo ($memoryFootprint / (1024 * 1024)) . ' MB' . PHP_EOL;

вы не можете ретроспективно вычислить точный след переменной, поскольку две переменные могут совместно использовать одно и то же выделенное пространство в памяти

давайте попробуем разделить память между двумя массивами, мы видим, что выделение второго массива стоит половину памяти первого. Когда мы снимаем первый, почти вся память по-прежнему используется вторым.

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)

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

для полного представления о том, как выделяется память в PHP и для чего использовать, я предлагаю вам прочитать следующие статьи: насколько велики PHP массивы (и значения) на самом деле? (Подсказка: большой!)

The Основы Подсчета Ссылок в документации PHP также есть много информации об использовании памяти, а также количество ссылок на общий сегмент данных.

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

  1. вычисление вновь выделенного пространства

если вы хотите вновь выделенное пространство после назначения, то вы должны использовать memory_get_usage() до и после выделения, как использовать его с копией дает вам ошибочное представление о реальности.

// 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";

помните, что если вы хотите сохранить результат первого memory_get_usage() переменная имеет чтобы уже существовать раньше, и memory_get_usage() должен быть вызван другой предыдущий раз, и все остальные функции тоже.

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

  1. расчет необходимого пространства

если вы хотите полагаться на функцию для вычисления необходимого пространства для хранения копии переменной, следующий код заботится о различных оптимизациях:

<?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

обратите внимание, что размер имени переменной имеет значение в выделенной памяти.

  1. Проверьте ваш код!!

переменная имеет базовый размер, определяемый внутренней структурой C, используемой в исходном коде PHP. Этот размер не колеблется в случае чисел. Для строк это добавило бы длину строки.

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;

если мы не возьмем инициализацию имя переменной в учете, мы уже знаем, сколько переменная использует (в случае чисел и строк):

44 байта в случае чисел

&plus; 24 байта в случае строк

&plus; длина строки (включая последний символ NUL)

(эти цифры могут меняться в зависимости от версии PHP)

вы должны округлить до нескольких 4 байт из-за памяти выравнивание. Если переменная находится в глобальном пространстве (а не внутри функции), она также выделит еще 64 байта.

поэтому, если вы хотите использовать один из кодов внутри этой страницы, вы должны проверить, что результат с помощью некоторых простых тестовых случаев (строк или чисел) соответствует этим данным с учетом каждого из показаний в этом сообщении ($_GLOBAL array, first function call, output buffer,...)

У меня была аналогичная проблема, и решение, которое я использовал, состояло в том, чтобы записать переменную в файл, а затем запустить filesize() на нем. Примерно так (непроверенный код):

function getVariableSize ( $foo ) 
{
    $tmpfile = "temp-" . microtime(true) . ".txt";
    file_put_contents($tmpfile, $foo);
    $size = filesize($tmpfile);
    unlink($tmpfile);
    return $size;
}

Это решение не очень быстро, потому что оно включает в себя диск IO, но оно должно дать вам что-то гораздо более точное, чем трюки memory_get_usage. Это просто зависит от того, сколько точность вам требуется.

никогда не пробовал, но следы Xdebug с xdebug.collect_assignmentS может быть достаточно.

function mesure($var){
    $start = memory_get_usage();
    if(is_string($var)){
        $newValue = $var . '';
    }elseif(is_numeric($var)){
        $newValue = $var + 0;
    }elseif(is_object($var)){
        $newValue = clone $var;
    }elseif(is_array($var)){
        $newValue = array_flip($var, []);
    }
    return memory_get_usage() - $start;
}

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

function getVariableUsage($var) {
  $total_memory = memory_get_usage();
  $tmp = unserialize(serialize($var));
  return memory_get_usage() - $total_memory; 
}

$var = "Hey, what's you doing?";
echo getVariableUsage($var);

зацените

http://www.phpzag.com/how-much-memory-do-php-variables-use/