我有由数据包组成的二进制文件,其序列化如下:
[Length][Payload][Length][Payload][Length][Payload]
长度始终为 4 个字节,并且值是可变的,没有特定的模式。长度值包括
[Length]
本身的 4 个字节。我需要提取文件中每个 [Length]
的第一个字节的字节位置。例如:
00 00 02 00 FF FF FF FF FF ...
00 01 3C E5 FF FF FF FF FF ...
00 00 A5 90 FF FF FF FF FF ...
^
Need to save all these indexes
这可以工作,但速度很慢,因为每个文件有超过 100k 的数据包:
data = mmap.mmap(filename.fileno(), 0, access=mmap.ACCESS_READ)
fileSize = os.path.getsize(filename.name)
address = 0
addresses = []
start = time.time()
while address < fileSize:
pkt_length = bytes2int(data[address:(address + 4)])
addresses.append(address)
address += pkt_length
end = time.time()
print(len(addresses))
print(end-start)
我可以用什么来更快地做到这一点?
编辑 2 使用操作系统库
start = time.time()
addresses = []
fp = os.open(fileName, os.O_RDONLY)
while True:
buf = os.read(fp, 4)
if not buf:
break
size = int.from_bytes(buf, byteorder='big')
addresses.append(os.lseek(fp, size-4, os.SEEK_CUR)) # -4 cause length already read
end = time.time()
print(len(addresses))
print(end-start)
结果:
45559456
179.0517611503601
编辑1 以下是 4.2GB 文件的性能示例:
45559456
21.271047115325928
RAM 消耗也相当高。
您是否尝试过直接读取和查找而不是映射:
while open(...) as fp:
while True:
buf = fp.read(4)
if not buf:
break
size = int.from_bytes(buf, byteorder='big')
size_list.append(size)
fp.seek(size, os.SEEK_CUR)
只是好奇这是否会更快。