Самый быстрый способ сохранить данные в памяти с Redis в Python - PullRequest
0 голосов
/ 12 сентября 2018

Мне нужно один раз сохранить и несколько раз загрузить несколько больших массивов в приложении-колбе с Python 3. Я изначально сохранял эти массивы на диске с помощью библиотеки json. Чтобы ускорить это, я использовал Redis на той же машине для хранения массива путем сериализации массива в строку JSON. Интересно, почему я не получаю улучшения (на самом деле это занимает больше времени на сервере, которым я пользуюсь), тогда как Redis хранит данные в оперативной памяти. Я предполагаю, что сериализация JSON не оптимизирована, но я понятия не имею, как я могу ускорить это:

import json
import redis
import os 
import time

current_folder = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_folder, "my_file")

my_array = [1]*10000000

with open(file_path, 'w') as outfile:
    json.dump(my_array, outfile)

start_time = time.time()
with open(file_path, 'r') as infile:
    my_array = json.load(infile)
print("JSON from disk  : ", time.time() - start_time)

r = redis.Redis()
my_array_as_string = json.dumps(my_array)
r.set("my_array_as_string", my_array_as_string)

start_time = time.time()
my_array_as_string = r.get("my_array_as_string")
print("Fetch from Redis:", time.time() - start_time)

start_time = time.time()
my_array = json.loads(my_array_as_string)
print("Parse JSON      :", time.time() - start_time)

Результат:

JSON from disk  : 1.075700044631958
Fetch from Redis: 0.078125
Parse JSON      : 1.0247752666473389

EDIT : кажется, что выборка из redis на самом деле быстрая, но разбор JSON довольно медленный. Есть ли способ получить массив напрямую из Redis без части сериализации JSON? Это то, что мы делаем с pyMySQL, и это быстро.

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Некоторое объяснение:

  1. Загрузка данных с диска не всегда означает доступ к диску, часто данные возвращаются из кэша ОС в оперативной памяти, и когда это происходит, это происходит даже быстрее, чем получение данных из Redis (удаляет сетевое соединение из общего времени)

  2. Основной убийцей производительности является разбор JSON (cpt. Очевидный)

  3. Разбор JSON с диска, скорее всего, выполняется параллельно с загрузкой данных (из файлового потока)

  4. Нет возможности разобрать поток с Redis (по крайней мере, я не знаю такого API)


Вы можете ускорить приложение с минимальными изменениями, просто сохранив файлы кеша на tmpfs . Это довольно близко к настройке Redis на том же сервере.

Согласитесь, @RoopakANelliat msgpack примерно в 4 раза быстрее, чем JSON. Изменение формата повысит производительность анализа (если это возможно).

0 голосов
/ 17 мая 2019

Я сделал мозг-плазма специально по этой причине - быстрая загрузка и перезагрузка больших объектов в приложении Flask.Это пространство имен объектов совместно используемой памяти для сериализуемых объектов Apache Arrow, включая pickle d-строки, сгенерированные pickle.dumps(...).

$ pip install brain-plasma
$ plasma_store -m 10000000 -s /tmp/plasma # 10MB memory
from brain_plasma import Brain
brain = Brain()

brain['a'] = [1]*10000
brain['a']
# >>> [1,1,1,1,...]

0 голосов
/ 17 сентября 2018

Я пробовал мариновать против json против msgpack против маршала.

Рассол намного медленнее, чем JSON. И msgpack как минимум в 4 раза быстрее, чем JSON. MsgPack выглядит как лучший вариант, который у вас есть.

Edit: Пробовал и маршал тоже. Маршал быстрее, чем JSON, но медленнее, чем msgpack.

Время истекло : рассол> JSON> Маршал> MsgPack
Занятое место : маршал> Пикл> Джсон> MsgPack

import time
import json
import pickle
import msgpack
import marshal
import sys

array = [1]*10000

start_time = time.time()
json_array = json.dumps(array)
print "JSON dumps: ", time.time() - start_time
print "JSON size: ", sys.getsizeof(json_array)
start_time = time.time()
_ = json.loads(json_array)
print "JSON loads: ", time.time() - start_time

# --------------

start_time = time.time()
pickled_object = pickle.dumps(array)
print "Pickle dumps: ", time.time() - start_time
print "Pickle size: ", sys.getsizeof(pickled_object)
start_time = time.time()
_ = pickle.loads(pickled_object)
print "Pickle loads: ", time.time() - start_time


# --------------

start_time = time.time()
package = msgpack.dumps(array)
print "Msg Pack dumps: ", time.time() - start_time
print "MsgPack size: ", sys.getsizeof(package)
start_time = time.time()
_ = msgpack.loads(package)
print "Msg Pack loads: ", time.time() - start_time

# --------------

start_time = time.time()
m_package = marshal.dumps(array)
print "Marshal dumps: ", time.time() - start_time
print "Marshal size: ", sys.getsizeof(m_package)
start_time = time.time()
_ = marshal.loads(m_package)
print "Marshal loads: ", time.time() - start_time

Результат:

    JSON dumps:  0.000760078430176
JSON size:  30037
JSON loads:  0.000488042831421
Pickle dumps:  0.0108790397644
Pickle size:  40043
Pickle loads:  0.0100247859955
Msg Pack dumps:  0.000202894210815
MsgPack size:  10040
Msg Pack loads:  7.58171081543e-05
Marshal dumps:  0.000118017196655
Marshal size:  50042
Marshal loads:  0.000118970870972
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...