2015-01-02 5 views
8

Я сделал небольшой тест, чтобы сравнить YAML и JSON скорость:Могу ли я ускорить YAML?

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()?

ответ

12

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

То, что происходит json библиотека языка Python кодирует встроенные типы данных языка Python directly into text chunks, заменив ' в " и удаление , здесь и там (упрощенно немного).

С другой стороны, pyyaml имеет значение construct a whole representation graph, прежде чем сериализовать его в строку.

Такие же вещи должны происходить назад при погрузке.

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

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

- UPDATE

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

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

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-получить:

$ apt-get install yaml-cpp-dev 

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

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

+1

Загрузка по-прежнему в 12 раз медленнее с помощью yaml.my sample - это список из 600 000 бесплатных словарей. Yaml не нужно делать ничего лишнего, кроме немного более сильного синтаксического анализа, который не должен занимать почти никакого дополнительного времени. – codeshot

+1

На mac: brew install yaml-cpp libyaml –

+0

Jivan, вы - кровавая легенда. Я собирался переписать код Python на C++, чтобы ускорить работу. Моему файлу 6MB yaml потребовалось 53 секунды для загрузки с использованием стандартного загрузчика ямлов и всего 3 секунды с помощью Cloader. – nevelis

0

Да, я также заметил, что 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, чтобы избежать конфликтов с другим программным обеспечением.

Смежные вопросы