首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Python中使用Redis最快地将数据保存在内存中

在Python中使用Redis最快地将数据保存在内存中
EN

Stack Overflow用户
提问于 2018-09-12 22:54:22
回答 4查看 5.5K关注 0票数 4

在使用Python3的flask应用程序中,我需要保存一次并加载多次大型数组。我最初将这些数组存储在json库的磁盘上。为了加快速度,我在同一台机器上使用Redis通过将数组序列化为JSON字符串来存储该数组。我想知道为什么我没有得到改进(实际上它在我使用的服务器上花费了更多的时间),而Redis将数据保存在RAM中。我猜JSON序列化没有优化,但我不知道如何加快速度:

代码语言:javascript
运行
复制
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)

结果:

代码语言:javascript
运行
复制
JSON from disk  : 1.075700044631958
Fetch from Redis: 0.078125
Parse JSON      : 1.0247752666473389

编辑:看起来从redis获取数据实际上很快,但是JSON解析相当慢。有没有一种方法可以不使用JSON序列化部分直接从Redis获取数组?这就是我们对pyMySQL所做的,而且速度很快。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-09-17 20:30:06

更新:2019年11月8日-在Python3.6上运行相同的测试

结果:

转储时间:JSON > msgpack >> marshal

加载时:JSON > pickle > msgpack > marshal

空间包:编组> JSON >> msgpack

代码语言:javascript
运行
复制
+---------+-----------+-----------+-------+
| package | dump time | load time | size  |
+---------+-----------+-----------+-------+
| json    | 0.00134   | 0.00079   | 30049 |
| pickle  | 0.00023   | 0.00019   | 20059 |
| msgpack | 0.00031   | 0.00012   | 10036 |
| marshal | 0.00022   | 0.00010   | 50038 |
+---------+-----------+-----------+-------+

我尝试了pickle vs json vs msgpack vs marshal。

Pickle比JSON慢得多。而且JSON 至少比快4倍。MsgPack看起来是你最好的选择。

编辑:也尝试了编组。Marshal比JSON快,但比msgpack慢。

耗时:Pickle > JSON > Marshal > MsgPack

空间占用:>腌黄瓜> Json > MsgPack

代码语言:javascript
运行
复制
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

结果:

代码语言:javascript
运行
复制
    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
票数 13
EN

Stack Overflow用户

发布于 2018-09-19 22:11:23

一些解释:

  1. 从磁盘加载数据并不总是意味着磁盘访问,通常是从内存中的OS缓存返回的数据,当这种情况发生时,这甚至比从Redis (从总时间中删除网络通信)获取数据更快
  2. 主要的性能杀手是JSON parsing (cpt )。很明显)从磁盘解析
  3. JSON最有可能是与数据加载并行完成的(从filestream)
  4. There解析Redis流没有选项(至少我不知道这样的API)

只需将缓存文件存储在tmpfs上,您就可以用最少的更改来加速应用程序。它与Redis在同一台服务器上的设置非常接近。

同意@RoopakANelliat msgpack比JSON快4倍左右。格式更改将提高解析性能(如果可能)。

票数 2
EN

Stack Overflow用户

发布于 2019-05-17 05:50:48

我开发brain-plasma就是为了这个原因--在Flask应用程序中快速加载和重新加载大对象。它是Apache Arrow可序列化对象的共享内存对象名称空间,包括由pickle.dumps(...)生成的pickle'd字节串。

代码语言:javascript
运行
复制
$ 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,...]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52298118

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档