Могу ли я ускорить YAML?

Я сделал небольшой тестовый пример для сравнения скорости YAML и JSON:

import json import yaml from datetime import datetime from random import randint NB_ROW=1024 print 'Does yaml is using libyaml ? ',yaml.__with_libyaml__ and 'yes' or 'no' dummy_data = [ { 'dummy_key_A_%s' % i: i, 'dummy_key_B_%s' % i: i } for i in xrange(NB_ROW) ] with open('perf_json_yaml.yaml','w') as fh: t1 = datetime.now() yaml.safe_dump(dummy_data, fh, encoding='utf-8', default_flow_style=False) t2 = datetime.now() dty = (t2 - t1).total_seconds() print 'Dumping %s row into a yaml file : %s' % (NB_ROW,dty) with open('perf_json_yaml.json','w') as fh: t1 = datetime.now() json.dump(dummy_data,fh) t2 = datetime.now() dtj = (t2 - t1).total_seconds() print 'Dumping %s row into a json file : %s' % (NB_ROW,dtj) print "json is %dx faster for dumping" % (dty/dtj) with open('perf_json_yaml.yaml') as fh: t1 = datetime.now() data = yaml.safe_load(fh) t2 = datetime.now() dty = (t2 - t1).total_seconds() print 'Loading %s row from a yaml file : %s' % (NB_ROW,dty) with open('perf_json_yaml.json') as fh: t1 = datetime.now() data = json.load(fh) t2 = datetime.now() dtj = (t2 - t1).total_seconds() print 'Loading %s row into from json file : %s' % (NB_ROW,dtj) print "json is %dx faster for loading" % (dty/dtj) 

И результат:

 Does yaml is using libyaml ? yes Dumping 1024 row into a yaml file : 0.251139 Dumping 1024 row into a json file : 0.007725 json is 32x faster for dumping Loading 1024 row from a yaml file : 0.401224 Loading 1024 row into from json file : 0.001793 json is 223x faster for loading 

Я использую PyYAML 3.11 с библиотекой libyaml C на ubuntu 12.04. Я знаю, что json намного проще, чем yaml, но с коэффициентом 223x между json и yaml. Мне интересно, правильна ли моя конфигурация или нет.

У вас одинаковое соотношение скоростей?
Как ускорить yaml.load() ?

2 Solutions collect form web for “Могу ли я ускорить YAML?”

Вы, наверное, заметили, что синтаксис Python для структур данных очень похож на синтаксис JSON.

Что происходит, это json библиотека Python кодирует встроенные типы данных Python непосредственно в текстовые фрагменты , заменяя ' на " и удаляя , кое-где (чтобы упростить бит).

С другой стороны, pyyaml должен построить целый граф представления перед его сериализацией в строку.

При загрузке такой же материал должен происходить назад.

Единственным способом ускорения yaml.load() было бы написать новый Loader , но я сомневаюсь, что это может быть огромным скачком в производительности, за исключением случаев, когда вы готовы написать свой собственный однотипный сортировщик YAML , принимая следующий комментарий :

YAML создает граф, потому что это универсальный формат сериализации, который может представлять несколько ссылок на один и тот же объект. Если вы знаете, что объект не повторяется и появляются только базовые типы, вы можете использовать сериализатор json, он все равно будет действительным YAML.

ОБНОВЛЕНИЕ

То, что я сказал ранее, остается верным, но если вы используете Linux есть способ ускорить разбор Yaml . По умолчанию yaml Python использует парсер Python. Вы должны сказать, что хотите использовать парсер PyYaml C

Вы можете сделать это следующим образом:

 import yaml from yaml import CLoader as Loader, CDumper as Dumper dump = yaml.dump(dummy_data, fh, encoding='utf-8', default_flow_style=False, Dumper=Dumper) data = yaml.load(fh, Loader=Loader) 

Для этого вам необходимо yaml-cpp-dev , например, с помощью apt-get:

 $ apt-get install yaml-cpp-dev 

И PyYaml с LibYaml также. Но это уже имеет место на основе вашей продукции.

Я не могу проверить это прямо сейчас, потому что я запускаю OS X, и у brew есть некоторые проблемы с установкой yaml-cpp-dev но если вы будете следовать документации PyYaml , они довольно понятны, что производительность будет намного лучше.

Да, я также заметил, что JSON быстрее. Поэтому разумным подходом было бы преобразование YAML в JSON в первую очередь. Если вы не против рубина, то вы можете получить большое ускорение и полностью yaml :

 import commands, json def load_yaml_file(fn): ruby = "puts YAML.load_file('%s').to_json" % fn j = commands.getstatusoutput('ruby -ryaml -rjson -e "%s"' % ruby) return json.loads(j[1]) 

Вот сравнение для 100K записей:

 load_yaml_file: 0.95 s yaml.load: 7.53 s 

И за 1M записи:

 load_yaml_file: 11.55 s yaml.load: 77.08 s 

Если вы настаиваете на использовании yaml.load в любом случае, не забудьте включить его в virtualenv, чтобы избежать конфликтов с другим программным обеспечением.

  • Как получить список dict вместо использования collection.defaultdict в python
  • Разберите YAML и предположим, что определенный путь всегда является строкой
  • Получение ученого представления данных из неконтролируемого обучения в pylearn2
  • Обслуживание статического html в Google app engine Python
  • В чем заключается основное различие между pickle и yaml в Python?
  • Чтение YAML в python
  • Как использовать пользовательскую проверку подлинности с атрибутом login: required в app.yaml (движок Google для приложений, python)
  • Изменение YAML с использованием ruamel.yaml добавляет дополнительные новые строки
  • Python - лучший язык программирования в мире.