Pull to refresh

Сравнение скорости обработки JSON разными парсерами и браузерами

Reading time 6 min
Views 6.3K

Преамбула


Занимаясь сейчас написанием интерфейса/middleware для одной IPTV-STB приставки, столкнулся с достаточно медленной работой javascript-парсера встроенной Оперы при вызове eval (пока встроенной была не Опера, а ANT Galio все было еще печальнее, но это тема отдельного разговора). То есть, там вообще все работает медленно, т.к. это все-таки просто приставка, но в данном конкретном случае с тормозами надо было что-то делать — через ajax грузилась программа ТВ-передач, и пока eval парсил приходящую JSON-строку, приставка на действия пользователя вообще не откликалась (причем достаточно долго). В итоге я решил вопрос использованием JSONP, который заработал на приставке в несколько раз быстрее (а заодно и решил вопрос с кросс-доменностью), но попутно задумался над производительностью парсеров в принципе. На хабре нашел только одну статью про это, но JSONP там не было… Плюс в комментах были несколько позитивных критических замечаний, поэтому решил провести свое тестирование. Используются все парсеры с JSON.org и браузеры Opera 9.64, Firefox 3.5, Internet Explorer 8, Google Chrome 2, Safari 4.


Методика тестирования


В комментариях к вышеуказанной статье обращали внимание, что браузеры могут кэшировать результат парсинга, поэтому не вполне корректно одну и ту же строку просто «прогонять» сотню раз, чтобы получить достоверный результат. Кроме того, в JSONP парсинга как такового вообще нет — речь скорее идет о парсинге JavaScript как таковом.
В итоге был написан короткий php-скрипт, который стоит на сервере и генерирует по запросу JSON-строку, содержающую массив с заданным количеством объектов вот такого формата:
{
"key_string1" : "qkrlgthcnadzemsiuwvbfopxyj",
"key_string2" : "zbntiyjchfpsraudqxkgomvwle",
"key_int" : 25721,
"key_arr" : [21,25,19,16,10,4,27,17,6,12,22,29,5,1,26,28,23,14,24,13,3,18,30,15,2,11,8,20,9,7],
"key_float" : 2110.1
}

Содержимое свойств объектов заполняется каждый раз случайным образом, а сам скрипт вызывается с предотвращением кэширования.
Для самого тестирования была написана страница, запрашивающая разными способами с сервера JSON-строку с разным количеством объектов в массиве и замеряющая время скачивания и парсинга (в случае JSONP — все сразу). Для более точного результата все запросы проводились по 50 раз. Использованы следующие методы парсинга:
  • JSONP — в самом классическом варианте — подключаемый скрипт вызывает callback с JSON-объектом в качестве параметра. Основной недостаток — низкий уровень безопасности, т.к. в подключаемом скрипте может быть что угодно.
  • XMLHttpRequest + json2.js — это по сути обычный eval, только чуть-чуть облагороженный несколькими regexp'ами для проверки валидности самого кода JSON-строки. Недостаток — т.к. используется eval, все равно можно попробовать включить в строку js-код и «набедокурить» на клиенте.
  • XMLHttpRequest + json_parse.js — полноценный синтаксический разбор JSON. Eval не используется, поэтому с безопасностью все в порядке, а основной недостаток — низкая скорость работы.
  • XMLHttpRequest + json_sans_eval — парсер от Google. Не использует eval — поэтому безопасен, и использует минимум кода — поэтому быстр. :-) Недостаток — не проводит валидацию JSON-строки, поэтому если она «битая» или неправильная — результат непредсказуем. :-) В смысле — в результате работы парсинга будет возвращена какая-нибудь лабуда.
  • XMLHttpRequest + нативные парсеры JSON — я не мог не включить в это тестирование нативные парсеры JSON, которые присутствуют в последних версиях IE и FF. :-)


Тестировал все на домашнем компьютере (Athlon64 X2 5200+, 2Гб памяти, Windows XP SP2), а скрипты запускались с сервера, находящегося неподалеку в локальной сети (чтобы хоть немного повлиять положительно на задержки, связанные с транспортом). Заранее хочу предупредить, что эти самые транспортные задержки тем не менее присутствуют в полной мере (в районе 200мс), причем с немаленьким таким разбросом, поэтому акцентироваться на абсолютных значениях тестов не стоит — намного важнее относительное «на глазок» сравнение результатов разных парсеров и браузеров. Я пробовал тестировать на localhost'е, но запущенный под shttps php-cgi работает еще медленее, а создавать специальный стенд для тестирования было немного лениво.
И что касается браузеров. Использовались официальные последние версии официальных релизов, доступные на сайтах браузеров на 02.07.2009. Поэтому, например, Опера не 10-я — чего, может быть, многие бы хотели. IE6 тоже нет — я мог запустить его разве что в IETester, но мне кажется, что результаты оттуда были бы не вполне корректны. Тест прогонялся в единственной вкладке сразу после запуска каждого браузера. В процессе его работы разные браузеры по разному грузили процессор и потребляли разное количество памяти, но это — тема для отдельного исследования.

Результаты тестирования


Все результаты — в табличной форме. Для всех парсеров в первой строке приведено общее время выполнения в миллисекундах (запрос данных + парсинг), во второй (кроме JSONP) — время только парсинга. Сравнивать с JSONP имеет смысл только первую строчку, вторая служит только для сравнения остальных парсеров между собой.

Google Chrome 2
Парсер Количество объектов в массиве в строке JSON
25 50 100 200 400 800
JSONP 187 187 211 197 213 242
JSON_json2 189 189 193 200 220 253
JSON_json2 — parse 2 4 6 12 21 42
JSON_json_parse 192 194 198 212 241 311
JSON_json_parse — parse 4 6 11 22 45 92
JSON_json_sans_eval 190 190 191 231 240 259
JSON_json_sans_eval — parse 1 3 6 11 23 48


Firefox 3.5
Парсер Количество объектов в массиве в строке JSON
25 50 100 200 400 800
JSONP 212 215 219 222 233 277
JSON_json2 219 224 224 239 270 384
JSON_json2 — parse 3 6 12 25 51 106
JSON_json_parse 223 255 276 353 529 820
JSON_json_parse — parse 19 36 72 145 288 578
JSON_json_sans_eval 219 225 224 257 307 365
JSON_json_sans_eval — parse 5 8 16 31 62 123
JSON_native 198 211 219 233 244 261
JSON_native — parse 1 1 2 4 9 17


Opera 9.64
Парсер Количество объектов в массиве в строке JSON
25 50 100 200 400 800
JSONP 307 356 371 395 390 430
JSON_json2 323 332 344 391 463 693
JSON_json2 — parse 8 16 31 67 138 343
JSON_json_parse 316 333 363 438 553 829
JSON_json_parse — parse 11 22 54 112 231 476
JSON_json_sans_eval 311 323 352 380 436 588
JSON_json_sans_eval — parse 5 12 23 53 114 237


Internet Explorer 8
Парсер Количество объектов в массиве в строке JSON
25 50 100 200 400 800
JSONP 191 191 198 201 217 244
JSON_json2 216 204 212 218 251 220
JSON_json2 — parse 3 5 11 22 45 92
JSON_json_parse 238 287 399 523 864 1672
JSON_json_parse — parse 45 90 191 327 643 1443
JSON_json_sans_eval 203 213 273 306 412 681
JSON_json_sans_eval — parse 9 20 54 107 204 448
JSON_native 195 196 209 201 219 250
JSON_native — parse 1 1 4 5 11 27


Safari 4
Парсер Количество объектов в массиве в строке JSON
25 50 100 200 400 800
JSONP 204 228 208 221 238 280
JSON_json2 198 200 202 210 232 266
JSON_json2 — parse 1 2 4 8 16 31
JSON_json_parse 224 205 213 239 273 351
JSON_json_parse — parse 4 7 14 28 56 111
JSON_json_sans_eval 202 205 211 226 260 324
JSON_json_sans_eval — parse 3 5 10 20 41 80


UPD: deerua  нарисовал для каждого парсера симпатичные графики — радуемся:

JSONP
g1

JSON_json2
g2

JSON_json_parse
g3

JSON_json_sans_eval
g4

JSON_native
g5

Выводы


С одной стороны результаты достаточно нерепрезентативны — большинство отличий скрадывается 200 миллисекундной задержкой (и ее разбросом между разными запусками) при вызове серверного скрипта, который возвращает данные. С другой стороны ряд выводов сделать не только можно, но и нужно:
  1. JSONP действительно быстр! Его скорость одинакова во всех браузерах (разве что Опера подкачала), а масштабируемость намного лучше, чем у любых других парсеров. Скорость его работы зависит больше всего от самого сервера, отдающего контент, — отсюда и беспорядочный разброс в результатах. В любом случае, если нет специальных требований к безопасности на клиенте, то JSONP — оптимальный выбор для передачи и парсинга JSON-данных.
  2. Если речь не идет о больших объемах данных (файл на 800 объектов из этого теста занимает около 190кб) и использовании IE, то разница во времени между остальными парсерами не особо существенна. Имеется в виду полное время выполнения, а не только парсинг JSON.
  3. Встроенные JSON-парсеры в FF и IE показали лучшие результаты в том, что касается скорости именно парсинга. Учитывая еще, что они обеспечивают полную безопасность, — использовать их явно имеет смысл.
  4. Гугловский парсер json_sans_eval не сильно медленнее json2, работающего на классическом eval, зато обеспечивает высокий уровень безопасности. Поэтому если получаемый JSON-объект проходит потом отдельную валидацию в процессе использования, то это, очевидно, будет оптимальным компромиссом.
  5. Из браузеров лучше всего себя показали Chrome и Safari. Учитывая, что ноги у обоих растут из одного места — WebKit однозначно рулит. :-)
  6. Opera и Firefox выступили крайне средненько, а IE8 — неоднозначно: отличный нативный парсер и работа eval и одновременно ужасный «ручной» разбор строки. Очевидно, дело в отсталом js-движке.


Вот-с, надеюсь это было кому-нибудь интересно, кроме меня. :-) Возможно, позже я улучшу тест, убрав из нее транспортную составляющую, но для первоначальной оценки скорости парсеров и браузеров и этого, на мой взгляд, достаточно…

ps: А вот если бы Хаб позволял задавать bgcolor в строках таблиц — результаты были бы куда красивее…
Tags:
Hubs:
+27
Comments 31
Comments Comments 31

Articles