Можно ли использовать короткие целые (16-битные) в PHP? - PullRequest
5 голосов
/ 07 сентября 2010

Справочная информация: у меня есть большой двумерный массив целых чисел, который мне нужно загружать в память в PHP для каждого запроса Apache.Я хочу, чтобы он занимал меньше памяти.

PHP хранит целые числа в PHP_INT_SIZE байтах, что составляет 32 бита в большинстве систем.Все целые числа меньше 2 ^ 16, что означает, что они могут быть short int (например, в C).Правильно ли я считаю, что хранение коротких целых занимает половину оперативной памяти?

В идеале я хотел бы иметь возможность:

$s = (short) 1234; // takes up 2 bytes instead of 4

Дополнительная информация:

  • Массив занимает около 100 МБ ОЗУ и генерируется путем включения 30 МБ var_export () dump
  • Массив записывается в процессе cron.Только чтение должно быть эффективным (и быстрым) для памяти
  • Единственные операции, которые мне нужно сделать над целыми числами, - это сравнить все из них (<,>, ===), а затем прочитать несколько из них (аналогичен алгоритму Флойда-Варшалла )
  • Чтение каждого значения из БД слишком медленное, поскольку на запрос приходится несколько сотен миллионов операций чтения

Некоторыесумасшедшие идеи:

  • Использование pack () / unpack () , но при распаковке все равно будут храниться значения в 32-битных целых числах
  • Сохраните значения в виде пикселей на изображении и используйте PHP GD-библиотеку , чтобы прочитать их (это будет медленно)
  • Используйте shmop_read () и получитеПроцессы Apache совместно используют массив
  • Memcached может работать, но у меня нет опыта работы с ним, и я предполагаю, что он будет во много раз медленнее, чем собственный массив PHP
  • Изучите C ++ инаписать расширение PHP
  • Перекомпилировать PHP (или HipHop ?), чтобы использовать 2 байта дляr ints
  • Use Igbinary (полезно, но будет иметь такую ​​же проблему, как pack ())

Ответы [ 3 ]

4 голосов
/ 07 сентября 2010

Я бы не рекомендовал последний подход.: -)

Для быстрого решения я бы упаковал 2 ваших целых числа в 1 целое число PHP, используя это:

$big = $int1 + ($int2<<16);

And uppack as:

$int1 = $big & 65535;
$int2 = ($big>>16) & 65535;

Кроме того, БОЛЬШОЙ палец вверх для использования общей памяти.Это сделает ваше приложение быстрее.

2 голосов
/ 07 сентября 2010

Это не задача, для которой был разработан PHP.

Я рекомендую вам написать приложение, которое хранит данные в памяти и выполняет с ними вычисления, а затем взаимодействует с ним в PHP для получения результатов.

Целочисленный размер PHP на самом деле 64-битный на большинстве 64-битных Unix-подобных платформ.

Общая память - не очень хороший вариант, потому что вам все равно нужно копировать данные в область памяти PHP.

Написание расширения, которое хранит все в памяти и напрямую обращается к нему, возможно, но не очень практично, так как вам все равно придется использовать общую память (или какой-то другой механизм IPC), потому что вы обычно запускаете несколько процессов PHP.

1 голос
/ 07 сентября 2010

Я бы сгенерировал и сохранил массив в двоичном упакованном формате и извлекал числа только тогда, когда они вам нужны

function elem($n) {
    global $buf;
    return (ord($buf[$n << 1]) << 8) | ord($buf[$n << 1 | 1]);
}

$buf = file_get_contents(binary file generated by cron);
if(elem(2) > elem(10)).....

вы можете сделать его более изящным, написав класс, реализующий ArrayAccess, так что вы можете просто использовать myPackedArray [x] вместо elem (x) в остальной части кода.

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