Я работаю с большим массивом, который представляет собой карту высот, 1024x1024 и, конечно, я застрял с ограничением памяти. На моей тестовой машине я могу увеличить лимит памяти до 1 ГБ, если захочу, но на моем крошечном VPS с 256 ОЗУ это не вариант.
Я искал в стеке и в Google и нашел несколько слов «ну, вы используют PHP не из-за эффективности памяти, откажитесь от этого и перепишите на c ++ "и, честно говоря, это нормально, и я признаю, что PHP любит память.
Но, копаясь больше в управлении памятью PHP, я не нашел, какая память потребляет каждый тип данных . Или если приведение к другому типу данных снижает потребление памяти.
Единственный метод "оптимизации", который я нашел, заключался в отключении переменных и массивов, вот и все.
Преобразование кода в C ++ с использованием некоторых анализаторов PHP решило бы проблему?
Спасибо!
Если вам нужен реальный индексированный массив, используйте SplFixedArray . Он использует меньше памяти. Кроме того, PHP 5.3 имеет гораздо лучший сборщик мусора.
Кроме этого, PHP будет использовать больше памяти, чем более тщательно написанный эквивалент C / C ++.
Использование памяти для целочисленного массива 1024x1024:
как измерено 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, для обработки этих данных, если скорость равна любого беспокойства.
Немного поздно стороне, но если у Вас есть многомерный массив, можно сохранить много 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.