识别python中全空字符串的最快方法

时间:2018-09-08 20:44:38

标签: python performance

假设性能至关重要的代码部分从磁盘文件中读取大小相等的数据块。如何在最短的时间内检测到全空的字符串/数据块?

这是我当前的代码:

# 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"

但是它比第一种方法还要慢。

关于如何提高性能的任何建议? 谢谢。

1 个答案:

答案 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所需的迭代次数减少四分之一,因为该数组将包含更少(更大)的元素,但是您必须确保与您的块大小保持一致。