Производительность кодирования и декодирования serialize и json — часть вторая

    Первая часть моей публикации получила ряд конструктивных комментариев, которые дали толчок разобраться в проблеме более детально.



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

    Исходных код теста, которым производились изменения немного переработан относительно первой части, но основа осталась прежней: http://pastie.org/242453

    Итак, рассмотрим самое простое — какое влияние оказывает на скорость работы возрастающая вложенность данных:



    Каждый элемент массива данных представлял собой:

    В первом случае:
    array ('1234667890', '1234667890', '1234667890', '1234667890', '1234667890');
    Во втором случае:
    array (array ('1234667890'), array ('1234667890'), array ('1234667890'), array ('1234667890'), array ('1234667890'));
    В третьем случае:
    array (array (array ('1234667890')),array (array ('1234667890')),array (array ('1234667890')),array (array ('1234667890')),array (array ('1234667890')));


    Вывод 1. С ростом вложенности упаковака json становится в разы быстрее serialize, однако обратные операции выполняются по скорости почти одинаково.

    Далее — рассмотрим целые и дробные числа (первые восемь групп столбцов на графике, метки «int» и «f»).


    В качестве данных в массиве выступали случайные числа от 0 до 100 (1), от 1000 до 10 000 (2), от 100 000 до 1 000 000 (3) и от 1 000 000 до 10 000 000 (4). Для первых четырёх колонок бралось целое число, для второй четвёрки — дробное.

    Вывод 2. На целых числах json чуть быстрее при упаковке, и чуть медленнее при распаковке.

    Вывод 3. На дробных числах json в разы быстрее при упаковке, и чуть медленнее при распаковке.

    Самое интересное — последние восемь групп столбцов. Там в качестве элементов массива данных выступают случайные последовательности из 5, 20, 50 и 100 латинских символов (l) и кириллицы в UTF-8 (k).

    Вывод 4. На длинных латинских строках json в разы медленнее.

    Вывод 5. На символах UTF-8 json в разы быстрее.

    В эпилоге хочется сказать, что все эти исследования несли больше теоретическую, нежели практическую ценность — ибо в каждом конкретном случае тип данных будет смешанным и вам понадобятся тесты именно под ваши данные. Плюс — речь идёт действительно о таких микроскопических выигрышах, пользу от которых можно увидеть разве что при ОЧЕНЬ больших объемах данных.

    PS: Первая данного повествования была опубликована на моём личном блоге, после чего буквально за несколько минут набрала достаточно баллов, чтобы попать в блог PHP. После чего совершенно непостижимым для меня образом попала на первую страницу, что меня несказанно порадовало =)

    Комментарии 21

      +1
      Спасибо, интересно. Но у вас все типы относительно простые - массивы и строки. Для полноты кратины не хватает кодирования/декодирования объектов (экземпляров классов).
      0
      я что-то не совсем понимаю необходимость данного теста, если нужно передать массив/объект в JS через ajax — разве кто-то будет сомневаться чем это сделать?
      точно также, если мне на память нужно сохранить массив в базе, но не предполагается поиск по нему, а планируется его полная выборка в будущем или передача данных через url с кодирование base64, то чем вы будете пользоваться?
      вы молодец, потратили время на создание тестов, но как-то нерационально: описали очевидные вещи, был бы успех если бы статья кончилась: долой классические прототипы мышления, быстрее оказывается ТАК, а пока...
        0
        а зависит ли скорость json_decode от значения его второго параметра?

        ибо в умолчательном варианте вы, вообще-то, после decode получаете во-первых совсем не то, что закодировали, а во-вторых, насколько я понимаю, создание экземпляра объекта должно быть более тяжелой операцией, нежели создание массива.
          –1
          А Вы случайно не британский учёный?
            0
            json_decode
            This function will return false if the JSON encoded data is deeper than 127 elements.

            Недавно стакнулся с данной ситуацией, так что не всегда удобно использовать при больших объемов данных. Или использовать средства для работы с json не входящие в основную сборку php
              +3
              По моему, эта тема не стоит того, чтобы ее выносить для обсуждения (даже для первого поста). Возникший вопрос решается на коленке за пару минут, а выбор способа упаковки обусловлен в большей степени целями, но никак не скоростью.

              Не стоит заниматься преждевременной оптимизацией, это зло. Оптимизировать нужно тогда, когда у вас появятся проблемы с производительностью.
                +1
                casey, вы понимает различие между JSON и сериализацией? и когда что применяется?
                  –1
                  Да, здесь я разбирал применение одного и другого для хранения абстрактного массива данных.
                    0
                    вы видели что получается на выходе json_decode в том виде, в котором он у вас использован в коде теста?

                    Мне кажется, вы всё-же не понимаете зачем и для чего сделан json.

                    hint: он не подходит для хранения абстрактного php-шного массива данных.
                      0
                      Спасибо за дельный комментарий. Если я правильно понял, Вы имеете в виду то, что json_encode в php работает только с латиницей и utf-8?
                        +1
                        нет, я имел ввиду что две следующие строчки дадут разный результат и, как следствие, тест, который это не учитывает, не является корректным:

                        print_r (json_decode (json_encode(array ('one'=>'two'))); // будет инстанс stdClass с пропертёй one которая равна строке 'two'
                        print_r (unserialize (serialize(array ('one'=>'two'))); // выдаст именно то, что засовывали.

                        Это важно как с точки зрения корректности теста, так и с точки зрения быстродействия, т.к. манипуляции с объектами в пхп затратнее, чем манипуляции с массивами.

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

                        Т.е. в вашем тесте надо как минимум выставить второй параметр json_decode() в true.

                        Впрочем, это не отменяет того факта, что json не является средством сериализации произвольных данных.
                          0
                          Про реальные задачи - не в бровь, а в глаз - пользовался только serialize.
                          Спасибо за разъяснение.
                    0
                    Кстати, в этом вопросе "что когда применяется" есть и варианты. Например, для передачи данных в бекенде использовать между различными модулями системы в определенных целях JSON или сериализацию с распаковкой/упаковкой через какой-нибудь интерфейс (например для унифицированной архитектуры ПО). При этом JSON легко отдавать фронтенду без дополнительной обработки, а сериализированные объекты еще придется дополнительно обрабатывать для этого. И такой тест интересен перед проектированием самой системы, чтобы знать какие грабли лучше.
                      0
                      что для вас (front/back)end?
                        0
                        вопрос риторический. Бекенд - серверная часть. Фронт - браузерная
                        0
                        Честно говоря слабо могу себе представить ситуацию, когда переданные из другого модуля сериализованные данные должны быть сразу отправлены во фронтэнд, обычно такие данные используются для того чтобы изменить поведение конечного модуля, а их для этого соот-но нужно десериализовать.
                          0
                          Мне тоже, но использования сериализации дял передачи между модулями информации с последующей конвертацией в JSON - вполне возможный вариант
                      0
                      По моему, если необходимо передать данные на фронтэнд в необработанном виде то JSON значительно удобнее, он унифицирован, и имеет реализации для некоторых JS фреймворков (пр. MooTools) в отличии от сериализации, по крайней мере когда мне понадобилось передавать данные с сервера на клиент, для их последующей обработки и представления на клиенте в ввиде HTML, я воспользовался именно JSON'ом как прослойкой между PHP и MooTools, и не пожалел, получилось удобно, универсально и не привязано к конкретному отображению + немного разгрузил этим бекэнд от лишних преобразований + удобно кэшировать — один раз «отгенерировал» JSON-строку, положил в файл, а потом подгружать статичный файл.

                      Имеется еще желание попробовать для аналогичных целей применить «Protocol Buffers» от Google, если у кого то есть опыт его применения в связке с PHP было бы интересно послушать.
                        0
                        Сейчас пишу программу…
                        провёл тест…

                        На огромных массивах с 2х-кратной вложенностью — unserialize выигрывает по скорости в 2 раза у json_decode, хотя последний занимает в 1.5 меньше пространства.

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

                        Самое читаемое