python 读取字节流的时候,有多种方法可以读取,但是不同方法的效率差异较大,且和数据格式相关
解压字节流查询到有下面三种方法
struct.unpack('>' + 'type' * num, bytes_stream)
np.frombuffer(bytes_stream, dtype = np.dtype('type'), count = num)
np.frombuffer(bytes_stream, dtype = np.dtype('type,' * num))[0]
第一个实验,a 字节流中存了 2000 个 uint16
第二个实验,b 字节流中存了 1000 个结构体,每个结构体由一个 uint16 和 float32 组成
这三种方法均可以成功解压,但是速度差异较大,具体如下
import time
import struct
import numpy as np
# encode data to bytes stream
num1 = 2000
a = range(num1)
bytes_stream1 = struct.pack('>' + num1 * 'H', *a)
num2 = 1000
b = range(num2 * 2)
bytes_stream2 = struct.pack('>' + num2 * 'Hf', *b)
count = 1000
# decode bytes to data a
t0 = time.time()
for i in range(count):
data1 = struct.unpack('>' + 'H' * num1, bytes_stream1)
data1 = np.array(data1, dtype = 'f8')
t1 = time.time()
for i in range(count):
data2 = np.frombuffer(bytes_stream1, dtype = np.dtype('>u2'), count = num1)
data2 = data2.astype(dtype = 'f8')
t2 = time.time()
for i in range(count):
data3 = np.frombuffer(bytes_stream1, dtype = np.dtype('>u2,' * num1))[0]
data3 = np.array(data3.tolist(), dtype = 'f8')
# decode bytes to data b
t3 = time.time()
for i in range(count):
data4 = struct.unpack('>' + 'Hf' * num2, bytes_stream2)
data4 = np.array(data4, dtype = 'f8')
t4 = time.time()
for i in range(count):
data5 = np.frombuffer(bytes_stream2, dtype = np.dtype('>u2, >f4'), count = num2)
data5 = list(zip(*data5))
data5 = np.array(data5, dtype = 'f8')
t5 = time.time()
for i in range(count):
data6 = np.frombuffer(bytes_stream2, dtype = np.dtype('>u2, >f4,' * num2))[0]
data6 = np.array(data6.tolist(), dtype = 'f8')
t6 = time.time()
print(t1 - t0)
print(t2 - t1)
print(t3 - t2)
print(t4 - t3)
print(t5 - t4)
print(t6 - t5)
最后结果显示:
t1 - t0 = 0.073 s
t2 - t1 = 0.003 s
t3 - t2 = 3.129 s
对于简单类型的字节流来说,第二种方法速度最快
t1 - t0 = 0.076 s
t2 - t1 = 0.946 s
t3 - t2 = 3.110 s
对于复杂类型的字节流来说,第一种方法速度最快,第二种方法 np.frombuffer 其实读取的时候也是非常快的,时间接近 0.003 s,但是读出的数据为 tuple 组成的 list,为了转换成 np.array,做了对应的后处理,速度主要卡在步骤 list(zip(*data5))