Задать вопрос

Как правильно определить потребляемую память?

В PHP.ini стоит огрничение потребляемой памяти на "2000M"
Такой код
$startMemory = memory_get_usage();

$array = range(1, 33000000);

print_r($endMemory = memory_get_usage() - $startMemory);
print_r(round($endMemory / 1024 / 1024) . ' MB');

Выдает такой результат
1073746000
1024 MB
Если мы увеличиваем массив еще на 1 млн
$array = range(1, 34000000);
То результатом становится
PHP Fatal error:  Allowed memory size of 2097152000 bytes exhausted (tried to allocate 2147483656 bytes)

То есть судя по ошибке, размер массива превысил 2000 МБ и составил 2048 МБ
Вопрос - как размер памяти, занимаемой массивом внезапно скакнул аж в 2 раза при добавлении всего 1 млн значений в 33-миллионный массив ?
Функция memory_get_usage() неверно определяет кол-во занимаемой памяти ?
  • Вопрос задан
  • 274 просмотра
Подписаться 4 Средний 1 комментарий
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Давайте определим точную границу, где проходит увеличение объёма потребляемой памяти. Это 33554432 элементов.
3355443210 = 200000016
Поищем предыдущий скачок. Он происходит на 16777216 элементах.
1677721610 = 100000016
Проверим дальше. Получим следующие значения:
838860810 = 80000016
419430410 = 40000016
209715210 = 20000016
104857610 = 10000016
...
810 = 816
Вывод - PHP резервирует память округляя количество элементов вверх до ближайшей степени двойки.
Ответ написан
REZ1DENT3
@REZ1DENT3
web-developer
Массивы хранятся в 2^x. Когда размер массива переваливает за выделенное количество памяти, то php автоматически выделяет под размер массива в 2 раза больше памяти. Что у вас и происходит.

Если стоит задача поиграть с range, то лучше написать свой аналог на генераторах.
function xrange(int $min, int $max): iterable {
    for ($i = $min; $i < $max; $i++) {
        yield $i;
    }
}

$startMemory = memory_get_usage();

$array = xrange(1, 34000000);
foreach ($array as $item) {}

print_r($endMemory = memory_get_usage() - $startMemory); // 568
print_r(round($endMemory / 1024 / 1024) . ' MB'); // 0 MB
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы