Почему глобальный массив $ _SERVER занимает в 13 раз больше памяти? - PullRequest
4 голосов
/ 08 декабря 2010

При создании нового массива (и элемента) с использованием простых массивов PHP следующий код использует 360 байтов в PHP 5.3 с APC и без него. Даже добавление элемента в $ _GET использует только 304 байта. Однако при создании дополнительного элемента в $ _SERVER этот же код использует 4 896 байт!

$mem = memory_get_usage();

//$array = array('HTTP_X_REQUESTED_WITH' => NULL);
$_SERVER['HTTP_X_REQUESTED_WITH'] = NULL;
//$_GET['HTTP_X_REQUESTED_WITH'] = NULL;

print (memory_get_usage() - $mem).' bytes<br>';
print memory_get_usage().' bytes (process)<br>';
print memory_get_peak_usage(TRUE). ' bytes (process peak)<br>';
print (memory_get_usage() - $mem).' bytes<br>';

Что в мире заставляет массив $ _SERVER использовать столько дополнительной памяти?

Ответы [ 2 ]

4 голосов
/ 08 декабря 2010

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

Если вас интересует механизм этого процесса, они доступны в zend_hash.c , строка 418.

Чтобы проверить это, возьмите var_dump вашего $ _SERVER и вставьте его в скрипт.Пожалуйста, убедитесь, что вы не просто протестировали фиктивную хеш-таблицу по нескольким причинам: (1) на самом деле существуют разные пути кода C для php «динамических массивов» и php «хеш-таблиц» (он конвертирует их для вас), и (2)проблема может заключаться в копировании такого количества строк в новую хеш-таблицу, чтобы избежать безопасности потока или издержек указателя.

2 голосов
/ 08 декабря 2010

Объяснение Майка о том, как PHP динамически распределяет внутреннюю хеш-таблицу для массивов, является точным объяснением. Удвоение размера очень эффективно для динамического размещения массивов.

Однако при запуске скрипта суперглобальные переменные $ _SERVER, $ _REQUEST, $ _POST, $ _GET и $ _ENV имеют фиксированный размер. Они также вообще не редактируются (я не одобряю это).

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

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