Сериализация с Igbinary

Дошли, наконец, руки поставить и протестировать PHP-расширение Igbinary, о котором сегодня и поведую.

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

$A = array(1, 2, 'three', true);
$s = serialize($A);
 
var_dump($s); // 'a:4:{i:0;i:1;i:1;i:2;i:2;s:5:"three";i:3;b:1;}'

Для подобных действий используются функции serialize() и unserialize. Кроме того сериализация происходит неявно для данных сессий, значений в мемкэше и др.

Основной недостаток стандартной сериализации: формат строки — слишком многословный. Именно эту проблему решает Igbinary, сохраняя данные в компактной двоичной последовательности.

Установка

На nix’ах всё просто. Идём на сайт расширения, скачиваем tar.gz, и всё как обычно: tar, phpize, configure, make, make install, extension=igbinary.so.

Для Windows, к сожалению, версии не нашёл.

Использование

Просто вместо serialize/unserialize используем igbinary_serialize() и igbinary_unserialize().

Для того, чтобы сессии сериализовали свои данные через Igbinary, в php.ini пишем:

session.serialize_handler=igbinary

Чтобы заставить это работать и для мемкэша, в теории нужно собрать php_memcached с --enable-memcached-igbinary, и установить опцию OPT_SERIALIZER. У меня правда с первых двух раз php_memcached не собрался, а третий раз я пытаться не стал, так что отвечать за это не могу.

Ну и следует учитывать, что если у вас в мемкэше уже лежат данные, сериализованные дедовским способом, после подключения Igbinary, вытащить их будет проблемно.

Тестирование

Исходники теста здесь

Тестировалось на Ubuntu 9.10, PHP 5.3.2-dev

Результаты для Integer:

Integer
          Serialize Igbinary /
Time ser   167 ms    82 ms  2,0
Time unser 111 ms   100 ms  1,1
Size	   1 737    706     2,5
Bytes / El  17,4    7,1	
 
Integer Small
          Serialize Igbinary /
Time ser   143 ms   71 ms   2,0
Time unser  99 ms   83 ms   1,2
Size        991     406     2,4
Bytes / El  9,9     4,1	
 
Integer Big
           Serialize Igbinary /
Time ser    143 ms   75 ms   1,9
Time unser  116 ms   84 ms   1,4
Size        1 798    706     2,5
Bytes / El  18,0     7,1

Сериализовались массивы из 100 элементов (по 1000 циклов на тест).
Integer — числа по рандому, Integer Small — числа до 100, Integer Big — числа более 1 000 000 000.

Как видно, сериализует Igbinary, практически, вдвое быстрее. Десериализует тоже шустро. Но главное, что нас интересует, это размер получившейся строки.

Так как стандартный serialize сохраняет числа в виде строки, то очевидно, чем большего порядка число, тем длинее его представление. «0» займёт 4 байта («i:0;»), «10» уже 4. Для массива в тесте Integer Big приходится по 18 байт на элемент.

Igbinary же мало того, что хранит всё в двоичном виде, так и использует не один тип iteger (в 4 байта), а разные в зависимости от числа. Если число можно хранить в 1 байте, то хранится в 1 байте.

В итоге Igbinary сжимает данные в 2,5 раза лучше, чем serialize.

Float
           Serialize  Igbinary /
Time ser    1 388 ms    74 ms  18,9
Time unser    868 ms    86 ms  10,1
Size          5 650     1 085   5,2
Bytes / El     56,5     10,9

Теперь float. Здесь с serialize() вообще мрак кромешный. Он пытается вытащить из двоичного представления в памяти все возможные разряды и сохранить их: 1/3 = 'd:0.333333333333333314829616256247390992939472198486328125;'. А так как igbinary сам двоичный, ему проще.

В итоге 5-кратное преимущество по размеру и 20-кратное по скорости.

String
         Serialize  Igbinary /
Time ser   147 ms    205 ms 0,7
Time unser 120 ms    121 ms 1,0
Size       2 798     1 891  1,5
Bytes / El  28,0     18,9	
 
String-Keys
          Serialize Igbinary /
Time ser    157 ms   321 ms 0,5
Time unser  160 ms   155 ms 1,0
Size         4 066    2 877 1,4
Bytes / El    40,7     28,8

String — порядковый массив строк, String-Keys — ассоциативный массив со строковыми ключами.

Строки, они и в Африке строки, и имеют одно и тоже представление для обоих «сериализаторов». Igbinary выигрывает за счёт более компактной служебной информации. Здесь много зависит от величины строк, чем длинее строка, тем меньше будет разница в размерах.

Обращает на себя внимание, что по скорости стандартные средства на этот раз обошли Igbinary.

Резюме

Вобщем, Igbinary отличная приблуда. Пользуйтесь и не пожалеете, если у вас, конечно, не винда.

8 комментариев »

Leave a comment