Python有两个多进程共享资源方法,Manager支撑dict,list等类型资源共享。本质上是新建了一个子进程,用Pipe进行通信。
Share_memory实现方法不清楚。
官方说Share_memory的方法性能较高,但是形式不灵活(只支撑bytearray类型的数据共享)
Manager的方法方式灵活,支撑dict list array等类型,但是性能较低。
我之前用manager进行通信,确实很慢,所以我比较好奇它们性能到底差多少,如果用memory是不是可以优化很多。
测试一下:
if __name__ == '__main__':
manager = Manager()
pool = manager.dict({})
for i in range(2):
pool[i] = manager.list([])
# mem方法
mem = shared_memory.SharedMemory(create=True, size=4096)
# 测试经典方法
last_time = time.time()
for i in range(1000):
pool[0].append(['r'])
print("manager方法用时 "+str(time.time()-last_time))
last_time = time.time()
for i in range(500):
t = b'rrrr'
mem.buf[i:i+4] = t
print("mem方法用时 "+str(time.time()-last_time))
pass
结果:
manager方法用时 2.211533308029175
mem方法用时 0.0
很夸张,性能差了太多了。但是从mem拿出来的数据没办法直接用,必须unpack,然后再pack回去,再拷贝到内存里。这个时间也必须算上去。
于是在循环里加上:
t = struct.unpack('4s', t)[0] # 解封
t = struct.pack('4s', t) # 把str封装
结果
manager方法用时 2.187955379486084
mem方法用时 0.0
性能差距还是很夸张。
那么如果写入前,unpack不止一条数据,那么效率怎么样?其实就是pack+mem和Manager之间的比较。假设在写入前,需要首先unpack一半的数据(平均情况)
于是把它放在一个循环里面:
last_time = time.time()
for j in range(1000):
for i in range(500):
t = b'rrrr'
t = struct.unpack('4s', t)[0] # 解封
t = struct.pack('4s', t) # 把str封装
mem.buf[i:i+4] = t
print("mem方法用时 "+str(time.time()-last_time))
pass
结果:
manager方法用时 2.143948554992676
mem方法用时 0.29584312438964844
总结:如果单纯的读写,性能差了至少1000多倍,如果加上struct的损失,性能大概差了6-7倍
因此能用mem就用mem。