C обертка Python библиотека Json Слайсер медленнее, чем чистая Python i json библиотека - PullRequest
0 голосов
/ 13 января 2020

Согласно официальной документации (https://pypi.org/project/jsonslicer/), базовая c конфигурация слайсера Json дает 586,5 тыс. Объектов / с c, i json с Python при серверная часть выдает 32,2 тыс. объектов / сек c, а i json с C серверной частью (i json .yajl2_cffi) - 75,7 тыс. объектов / сек c.

при Я использовал две библиотеки в глубоко вложенном JSON файле размером 5 ГБ, ожидалось, что Slicer Json, являющийся оберткой для YAJL (https://lloyd.github.io/yajl/), будет работать быстрее, чем я json с чистой Python реализацией. Тем не менее, время, необходимое Json Slicer, составило 607,8014905452728 SE c, в то время как i json заняло 308,19292974472046 SE c.

По разным источникам (https://lpetr.org/2016/05/30/faster-json-parsing-python-ijson/, http://explique.me/Ijson/), i json с C должен работать быстрее, чем с Python back-end. Однако время, затраченное i json с C backend, составило 2016.68796280378929 se c.

Такое поведение наблюдалось при различных запусках в разных случаях на разных наборах Json файлов разных размеров.

Моя конфигурация системы - Intel i7 с 20 ГБ ОЗУ. Во время выполнения сценария не использовалась многопроцессорная обработка.

Пожалуйста, кто-нибудь может объяснить причину root такого странного поведения? Также, пожалуйста, дайте мне знать решение этой проблемы.

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Имейте в виду, что с версии 2.4 у i json есть новый yajl2_c бэкэнд, записанный полностью в C (то есть без использования cffi или ctypes), который в ~ 10 раз быстрее, чем другие. И, начиная с версии 2.5, она выбрана по умолчанию, если она присутствует в вашей установке (вероятно, то, что произошло в вашем случае, следовательно, вы увидели более быстрое выполнение). А начиная с версии 2.6 появился новый метод kvitems, который избегает создания полного объекта и выполняет итерации по его элементам, что полезно в некоторых ситуациях.

Исторически не было yajl2_c бэкэнда, поэтому, когда люди ссылались на «C backend» на самом деле был yajl2_cffi backend. Кроме того, у людей все еще может возникнуть впечатление, что по умолчанию i json используется python.

Итак, чтобы ответить на ваш вопрос: вы, вероятно, используете i json с yajl2_c бэкэнд и работает быстрее, чем JsonSlicer.

0 голосов
/ 22 января 2020

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

По умолчанию i json копирует вложенный документ в Python dict / list после первоначального соответствие шаблону произошло. Это влечет за собой стоимость. Если вы хотите манипулировать частью документа в Python (а не извлекать скаляр / строку), вам все равно нужно выполнить конвертацию. С реализацией C, выполняющей синтаксический анализ, это требует превращения переменной C в Python.

При работе с глубокой структурой данных, которую вы должны загружать много, вы можете обнаружить, что Преимущества синтаксического анализа файла в C сводятся на нет из-за стоимости конвертации в Python, после чего чистая реализация Python обходит некоторые из затрат на конвертацию.

jsonslicer невероятно быстр для простого извлечения задач, но это также будет сталкиваться с аналогичными ограничениями по мере роста сложности извлечения. У меня есть несжатый файл JSON размером 970 МБ, состоящий из списка документов. В моем случае выбор тривиальной строки из свойства 3-го уровня выглядит следующим образом:

with gzip.open('big_docs.json.gz') as file:
for thing in JsonSlicer(file, (None, 'key')):
    # print(thing)
    if thing == 'special_value':
        pass


with gzip.open('big_docs.json.gz') as file:
    for thing in ijson.items(file, 'item'):
        if thing['key'] == 'special_value':
            pass
  • i json (используется связывание по умолчанию C) - 363s
  • я json (чистый Python) - 686 с
  • jsonslicer - 15 с

В этом несправедливом сравнении jsonslicer может избежать преобразования чего угодно, кроме строки, в Python практически нулевая стоимость, поэтому результат поразительно быстр. Мое наивное использование i json должно выполнять гораздо больше работы.

В этом случае, если я копаю два слоя глубже, не меняя взаимодействие, я получаю:

  • i json - 350 с
  • i json (чистый python) - 667 с
  • jsonslicer - 16 с

jsonslicer немного замедляется с проверкой большего количества, тогда как i json делает то же самое, но выигрывает за счет моделирования небольших разделов документа. Более сложные виды использования меняют баланс. Доказать, что приведение от C к Python - это то, почему ваш невидимый код медленнее, было бы сложно, но это может способствовать!

...