2012-03-12 1 views
2

Я вычисляю некоторые очень большие числа с помощью Python, и я хотел бы сохранить ранее рассчитанные результаты в Berkeley DB.Python: сравнение производительности с использованием `pickle` или` marshal` и с использованием `re`

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

Например, я получаю (m, n) в качестве своего результата, в одном случае это необходимо сохранить как "%d,%d" % (m, n) и прочитать его, используя re. Я также могу хранить кортеж, используя pickle или marshal.

Какой у продукта лучший результат?

+0

Зачем вам использовать 're', чтобы разобрать это? Почему вас беспокоит производительность? Если вас беспокоит производительность, почему вы ожидаете, что интерпретация сохраненных данных станет узким местом? Какова природа ваших «ранее рассчитанных результатов»? Почему бы вам не хранить кортеж с несколькими столбцами? С каких пор базы данных ограничивают вас только строками? Ничего из этого не имеет никакого смысла. –

+0

@KarlKnechtel: У Berkeley DB нет столбцов. Это база данных с ключевыми значениями, одна из многих: Токио/Киотский кабинет, Мемкейч, Кассандра, Динамо, Волдеморт - другие примеры. –

+0

@KarlKnechtel Я использую Berkeley DB, поэтому у меня нет нескольких столбцов, если бы я использовал другую базу данных, тогда я бы не стал беспокоиться об этом. См. Http: // stackoverflow.com/questions/2399643/expressioning-multiple-columns-in-berkeley-db-in-python –

ответ

4

Для чистой скорости marshal даст вам самые быстрые результаты.

Тайминги:

>>> timeit.timeit("pickle.dumps([1,2,3])","import pickle",number=10000) 
0.2939901351928711 
>>> timeit.timeit("json.dumps([1,2,3])","import json",number=10000) 
0.09756112098693848 
>>> timeit.timeit("pickle.dumps([1,2,3])","import cPickle as pickle",number=10000) 
0.031056880950927734 
>>> timeit.timeit("marshal.dumps([1,2,3])","import marshal", number=10000) 
0.00703883171081543 
+0

Также выясняется, что если я не хочу, чтобы это было человечеством, маршал быстрее. –

+0

Добавил его в тайминги. :) – Amber

+0

Я тестировал маршала против msgpack, но маршал выиграл с точки зрения скорости. marshal avg time для 15000 операций по небольшому списку = 0.0003171195348103841, время для msgpack для одного теста = 0.0008052133083343506. Я не проверял использование пространства, хотя ... – Urjit

3

Время их и выяснить!

Я ожидал бы, что cPickle будет самым быстрым, но это не гарантия.

+1

Обратите внимание, что OP не упоминает версию Python, а 'cPickle' не существует отдельно от' pickle' в Py3 - 'pickle' предоставит оптимизированную версию его существующей версии и в противном случае вернется к версии pure-python. – lvc

1

Заканчивать shelve, простой настойчивый магазин ключ-значение с помощью словаря, как API, который использует pickle сериализовать объекты.

2

Когда кто-то думает о производительности он должен помнить 3 вещи:

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

Например , вот результаты моего benchmark:

jimilian$ python3.5 serializators.py 
iterations= 100000 
data= 'avzvasdklfjhaskldjfhkweljrqlkjb*@&$Y)(!#&[email protected]#lkjabfsdflb(*[email protected]#$(GKLJBmnz,bv(PGDFLKJ' 
==== DUMP ==== 
Pickle: 
>> 0.09806302400829736 
Json: 2.0.9 
>> 0.12253901800431777 
Marshal: 4 
>> 0.09477431800041813 
Msgpack: (0, 4, 7) 
>> 0.16701826300413813 

==== LOAD ==== 
Pickle: 
>> 0.10376790800364688 
Json: 2.0.9 
>> 0.30041573599737603 
Marshal: 4 
>> 0.034003349996055476 
Msgpack: (0, 4, 7) 
>> 0.061493027009419166 

jimilian$ python3.5 serializators.py 
iterations= 100000 
data= [1,2,3]*100 
==== DUMP ==== 
Pickle: 
>> 0.9678693519963417 
Json: 2.0.9 
>> 4.494351467001252 
Marshal: 4 
>> 0.8597690019960282 
Msgpack: (0, 4, 7) 
>> 1.2778299400088144 

==== LOAD ==== 
Pickle: 
>> 1.0350999219954247 
Json: 2.0.9 
>> 3.349724347004667 
Marshal: 4 
>> 0.468191737003508 
Msgpack: (0, 4, 7) 
>> 0.3629750510008307 

jimilian$ python2.7 serializators.py 
iterations= 100000 
data= [1,2,3]*100 
==== DUMP ==== 
Pickle: 
>> 50.5894570351 
Json: 2.0.9 
>> 2.69190311432 
cPickle: 1.71 
>> 5.14689707756 
Marshal: 2 
>> 0.539206981659 
Msgpack: (0, 4, 7) 
>> 0.752672195435 

==== LOAD ==== 
Pickle: 
>> 58.8052768707 
Json: 2.0.9 
>> 3.50090789795 
cPickle: 1.71 
>> 8.46298909187 
Marshal: 2 
>> 0.469168901443 
Msgpack: (0, 4, 7) 
>> 0.315001010895 

Итак, как вы можете видеть, что иногда лучше использовать Pickle (python3, длинные строки, свалка), иногда - msgpack (python3, длинный массив, нагрузка), в python2 - все работает совершенно по-другому. Вот почему никто не может дать определенный ответ, который будет действителен для всех (ожидайте этого;)).

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