Intereting Posts
Пространства имен в php 5.2 Настройка переменной окружения PHP при запуске сценария командной строки imagecreatefromstring (): данные не находятся в распознанном формате в Symfony2 – создайте фильтр Doctrine для выбора текущих пользовательских данных Как предотвратить множественные логины на веб-сайте PHP Предотвращение одновременного доступа к строке таблицы db Не удается получить доступ к веб-приложениям apache локально с использованием имени IP или ПК Инструмент проверки правописания PHP Лучший способ автоматического удаления комментариев из PHP-кода Получение данных JSON для Highcharts с несколькими сериями? Создание текстового поля красного цвета при возникновении ошибки в форме regex php несколько экземпляров и пары PHP, если один или два равны Dropstrap Dropdown не работает – выпадающее меню не переключается отправить gcm-сообщение в группах из 1000 пользователей всем 10000 пользователям

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

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

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

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

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

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

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

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

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

PHP-памяти профилировщик

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

Наконец, откройте файл callgrind.out с помощью KCachegrind

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

Прежде всего установите Google gftftools , загрузив последний пакет здесь: 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 

pprof создаст новое окно в вашем существующем сеансе браузера, как показано ниже:

Профилирование памяти PHP с помощью memprof и gperftools

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

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

Подробнее см. Здесь .

Черный огонь

Blackfire является профилировщиком PHP от SensioLabs, парней Symfony2 https://blackfire.io/

Если вы используете puphpet для настройки своей виртуальной машины, вы будете рады узнать, что она поддерживается 😉

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

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

дляр

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

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

  • использование процессора

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

  • вывода в формате Google Trace Event

  • подпись функций

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

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

DBG

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

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

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

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

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

  • Ввести / Выйти / Перевернуть / Запустить в функциональность курсора

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

  • Глобальные контрольные точки

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

  • Несколько одновременных сеансов для параллельной отладки

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

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

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

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

 $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 бит.

Видеть:

  • memory_get_usage() – возвращает объем памяти, выделенный для PHP
  • memory_get_peak_usage() – возвращает пик памяти, выделенный PHP

Обратите внимание, что это не даст вам использование памяти определенной переменной.

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

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

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

 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) с 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) с 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? (Подсказка: БОЛЬШОЙ!)

Основы подсчета ссылок в документации 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 байта в случае чисел

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

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

(эти числа могут меняться в зависимости от версии PHP)

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

Поэтому, если вы хотите использовать один из кодов внутри этой страницы, вам нужно проверить, соответствуют ли результаты с помощью некоторых простых тестовых примеров (строк или чисел) эти данные с учетом каждого из указаний в этом сообщении (массив $ _GLOBAL, первый вызов функции, выходной буфер, …)

Вы можете выбрать вычисление разности памяти по возвращаемому значению обратного вызова. Это более элегантное решение, доступное в 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; 

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

 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_assignment s могут быть достаточно.

 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/