我将从描述我的问题开始。我有一个二进制文件(认为它是一个相对较大的文件,例如1GiB),由8-字节的序列组成。我需要创建两个快速例程:
在该文件中搜索第一个8字节序列的索引,该序列等于0x0000000000000000
。
在该文件中搜索与0xFFFFFFFFFFFFFFFF
不同的第一个8-字节序列的索引。
请注意,这两个例程都需要搜索对齐的序列,这意味着匹配应该从序列的开头开始。我可以更改文件格式(如下所示),但我需要它能够表示一个庞大的整数列表。此外,这个文件将从许多脚本(比如说,大约100个)同时访问(读取/更新),但是我使用fcntl.flock
来避免灾难。你知道吗
到目前为止,我在每个8字节序列之前添加了一个字节分隔符(\xAA
),以使搜索更容易而不发生冲突。因此,我认为第一个问题已经解决,因为我可以使用mmap.find
来搜索0xAA0000000000000000
的第一个出现,但是我要解决第二个问题。你知道吗
目前,为了解决第二个问题,我正在使用下面应用于mmap
的regex,但我不知道是否以及如何进一步改进它(我将它分成多行,以使其更易于阅读)。你知道吗
b"\xaa(?:" \
b"[^\xff].......|" \
b".[^\xff]......|" \
b"..[^\xff].....|" \
b"...[^\xff]....|" \
b"....[^\xff]...|" \
b".....[^\xff]..|" \
b"......[^\xff].|" \
b".......[^\xff])"
为了测试这两种方法的性能,我做了下面的压力测试。它创建一个~1GiB文件,其中包含每个问题的最坏情况,即搜索需要完全解析每个序列,并尝试执行我上面提出的解决方案。你知道吗
import re
import mmap
import time
zeros = b"\xaa" + (b"\x00" * 8)
ones = b"\xaa" + (b"\xff" * 8)
regex = b"\xaa(?:" \
b"[^\xff].......|" \
b".[^\xff]......|" \
b"..[^\xff].....|" \
b"...[^\xff]....|" \
b"....[^\xff]...|" \
b".....[^\xff]..|" \
b"......[^\xff].|" \
b".......[^\xff])"
reg = re.compile(regex)
file = open("1gib", "wb")
file.write(ones * 128 * 1024 * 1024)
file.close()
file = open("1gib", "rb+")
mem = mmap.mmap(file.fileno(), 0)
start = time.time()
reg.search(mem)
print(time.time() - start) # 17.609468460083008
mem.close()
file.close()
file = open("1gib", "wb")
file.write((zeros[ : -1 ] + b"\xff") * 128 * 1024 * 1024)
file.close()
file = open("1gib", "rb+")
mem = mmap.mmap(file.fileno(), 0)
start = time.time()
mem.find(zeros)
print(time.time() - start) # 1.539649248123169
mem.close()
file.close()
从运行时可以看出find
策略比regex策略快11.5倍。如何改进第二种策略,使之与第一种策略一样快?你知道吗
请注意,我对第一个策略的性能很满意,但如果您有任何改进建议,我愿意:)
非常感谢
目前没有回答
相关问题 更多 >
编程相关推荐