假设性能至关重要的代码部分从磁盘文件中读取大小相等的数据块。如何在最短的时间内检测到全空的字符串/数据块?
这是我当前的代码:
# options.blocksize = 1024*1024
f, dummy = do_open(dev, 'r')
zeroblock = '\0'*options.blocksize
while True:
block = f.read(options.blocksize)
if not block:
break
if block == zeroblock:
csum = "0000"
如您所见,我正在将全空块与从文件读取的块进行比较。此方法有效,但对于较大的块,需要花费大量时间进行比较。
我还尝试了计算NULL发生次数:
# options.blocksize = 1024*1024
f, dummy = do_open(dev, 'r')
zeroblock = '\0'*options.blocksize
while True:
block = f.read(options.blocksize)
if not block:
break
if block.count('\0') == options.blocksize:
csum = "0000"
但是它比第一种方法还要慢。
关于如何提高性能的任何建议? 谢谢。
答案 0 :(得分:2)
尝试使用if block == zeroblock:
而不是if not sum(block):
。零加在一起应该很快。
if not any(block):
应该差不多快,但是对于足够大的块可能会更好。 (它在第一个非零位置上具有快捷方式。)
请注意,这不适用于普通的unicode字符串,仅适用于字节字符串b''
,因为字节字符串迭代器返回的是整数,而不是1个字符的字符串。这意味着您必须使用open()
而不是'rb'
以二进制模式'r'
来存储文件。
Python 2没有bytes
。它使用的旧str
类型是基于字节的,但是迭代器返回的是长度为1的字符串,而不是我们想要的整数。因此,您将想在Python 2中使用字节数组。要么升级Python,要么尝试类似的事情。
from array import array
f, dummy = do_open(dev, 'rb')
while True:
block = array('B') # 'B' means bytes. (Actually "unsigned char" in C.)
try:
block.fromfile(f, options.blocksize)
except EOFError: # Fewer bytes were left than blocksize.
pass # Remaining bytes were still appended though.
if not block:
break
if not any(block): # sum() might be faster depending on blocksize.
csum = "0000"
如果您知道文件均匀地分成块大小,则不需要try / except部分。
您也可以尝试array('L')
将数据加载为无符号长整型而不是字节。这可能会使sum
所需的迭代次数减少四分之一,因为该数组将包含更少(更大)的元素,但是您必须确保与您的块大小保持一致。