Оптимизация памяти в массиве PHP

Я работаю с большим массивом, который представляет собой карту высот, 1024x1024 и, конечно, я застрял с ограничением памяти. На моей тестовой машине я могу увеличить лимит памяти до 1 ГБ, если захочу, но на моем крошечном VPS с 256 ОЗУ это не вариант.

Я искал в стеке и в Google и нашел несколько слов «ну, вы используют PHP не из-за эффективности памяти, откажитесь от этого и перепишите на c ++ "и, честно говоря, это нормально, и я признаю, что PHP любит память.

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

Единственный метод "оптимизации", который я нашел, заключался в отключении переменных и массивов, вот и все.

Преобразование кода в C ++ с использованием некоторых анализаторов PHP решило бы проблему?

Спасибо!

25
задан Gabriel A. Zorrilla 13 June 2011 в 21:21
поделиться

2 ответа

Если вам нужен реальный индексированный массив, используйте SplFixedArray . Он использует меньше памяти. Кроме того, PHP 5.3 имеет гораздо лучший сборщик мусора.

Кроме этого, PHP будет использовать больше памяти, чем более тщательно написанный эквивалент C / C ++.

Использование памяти для целочисленного массива 1024x1024:

  • Стандартный массив: 218,756,848
  • SplFixedArray: 92,914,208

как измерено memory_get_peak_usage()

$array = new SplFixedArray(1024 * 1024); // array();
for ($i = 0; $i < 1024 * 1024; ++$i)
  $array[$i] = 0;

echo memory_get_peak_usage();

Обратите внимание, что тот же массив в C, использующий 64-битные целые, будет 8M.

Как и предполагали другие, вы можете упаковать данные в строку. Это медленнее, но намного более эффективно использует память. Если использовать 8-битные значения, это очень просто:

$x = str_repeat(chr(0), 1024*1024);
$x[$i] = chr($v & 0xff); // store value $v into $x[$i]
$v = ord($x[$i]);        // get value $v from $x[$i]

Здесь объем памяти будет составлять всего около 1,5 МБ (то есть при рассмотрении всех издержек PHP только с этим массивом целочисленных строк).

Для удовольствия я создал простой тест для создания 8-разрядных целых чисел 1024x1024 и последующей их циклической обработки один раз. Все упакованные версии использовали ArrayAccess так, чтобы код пользователя выглядел одинаково.

                   mem    write   read
array              218M   0.589s  0.176s
packed array       32.7M  1.85s   1.13s
packed spl array   13.8M  1.91s   1.18s
packed string      1.72M  1.11s   1.08s

В упакованных массивах использовались собственные 64-разрядные целые числа (для упаковки только 7 байтов, чтобы избежать обработки со знаком) и использовались упакованные строки ord и chr. Очевидно, что детали реализации и компьютерные спецификации немного повлияют, но я ожидаю, что вы получите аналогичные результаты.

Таким образом, хотя массив был в 6 раз быстрее, он также использовал 125-кратную память как следующую лучшую альтернативу: упакованные строки. Очевидно, что скорость не имеет значения, если у вас заканчивается память. (Когда я использовал упакованные строки напрямую без класса ArrayAccess, они были только в 3 раза медленнее, чем собственные массивы.)

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

48
ответ дан 28 November 2019 в 18:28
поделиться

Немного поздно стороне, но если у Вас есть многомерный массив, можно сохранить много RAM при хранении полного массива как json.

$array = [];

$data = [];
$data["a"] = "hello";
$data["b"] = "world";

Для хранения этого массива просто используйте:

$array[] = json_encode($data);

вместо

$array[] = $data;

, Если Вы хотите вернуть arrry, просто используйте что-то как:

$myData = json_decode($array[0], true);

я имел большой массив с 275 000 наборов и сохранил приблизительно 36%-е потребление RAM.

РЕДАКТИРОВАНИЕ: Я нашел более лучший путь, когда Вы архивируете строку json:

$array[] = gzencode(json_encode($data));

и разархивировали его, когда Вам нужен он:

$myData = json_decode(gzdecode($array[0], true));

Это сохранило меня почти 75% использования пика RAM.

0
ответ дан 28 November 2019 в 18:28
поделиться
Другие вопросы по тегам:

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