首页 > 解决方案 > 在python中识别全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 == 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"

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

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

标签: pythonperformance

解决方案


而不是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因为数组将包含更少(更大)的元素,但您必须确保它与您的块大小对齐。


推荐阅读