以块为单位处理比物理内存大得多的数据

以块为单位处理比物理内存大得多的数据,第1张

以块为单位处理比物理内存大得多的数据

常规键是您要迭代处理文件

如果您只处理文本文件,那么这很简单:一次

for line in f:
只能读取一行。(实际上,它可以缓冲所有内容,但是缓冲区足够小,您不必担心。)

如果您要处理其他特定文件类型(例如numpy二进制文件,CSV文件,XML文档等),则通常会有类似的特殊用途解决方案,但是除非您告诉我们什么,否则没人能向您描述它们您拥有的那种数据。

但是,如果您有通用的二进制文件怎么办?


首先,该

read
方法需要读取一个可选的最大字节。因此,代替此:

data = f.read()process(data)

你可以这样做:

while True:    data = f.read(8192)    if not data:        break    process(data)

您可能需要编写如下函数:

def chunks(f):    while True:        data = f.read(8192)        if not data: break        yield data

然后,您可以执行以下 *** 作:

for chunk in chunks(f):    process(chunk)

您也可以使用两个参数来执行此 *** 作

iter
,但是许多人发现它有点晦涩:

for chunk in iter(partial(f.read, 8192), b''):    process(chunk)

无论哪种方式,此选项都适用于下面的所有其他变体(单个除外

mmap
,这很琐碎,没有意义)。


那里的8192数字没有什么神奇的。通常,您确实希望2的幂,并且最好是系统页面大小的倍数。除此之外,无论您使用的是4KB还是4MB的性能,其性能都不会有太大变化。如果是,则必须测试哪种方法最适合您的用例。


无论如何,这假设您一次可以处理每个8K,而无需保留任何上下文。例如,如果您要将数据馈送到渐进式解码器或哈希器等中,那是完美的。

但是,如果您需要一次处理一个“块”,那么您的块最终可能会跨越8K边界。你怎么处理那件事呢?

这取决于如何在文件中分隔块,但是基本思路非常简单。例如,假设您使用NUL字节作为分隔符(不太可能,但很容易显示为玩具示例)。

data = b''while True:    buf = f.read(8192)    if not buf:        process(data)        break    data += buf    chunks = data.split(b'')    for chunk in chunks[:-1]:        process(chunk)    data = chunks[-1]

这种代码在网络中非常常见(因为

sockets
不能 只是“全部读取”,因此您 总是
必须读入缓冲区并分块放入消息中),因此在网络代码中可能会找到一些有用的示例,这些示例使用类似的协议为您的文件格式。


或者,您可以使用

mmap

如果您的虚拟内存大小大于文件大小,那么这很简单:

with mmap.mmap(f.fileno(), access=mmap.ACCESS_READ) as m:    process(m)

现在,

m
它就像一个巨大的
bytes
对象,就像您被调用
read()
来将整个内容读入内存一样,但是 *** 作系统将根据需要自动将位分页移入和移出内存。


如果您尝试读取的文件太大而无法容纳您的虚拟内存大小(例如,具有32位Python的4GB文件或具有64位Python的20EB文件),那么只有在2013年,如果要读取稀疏或虚拟文件(例如Linux上另一个进程的VM文件),则必须实现窗口化-
一次在文件的一部分中实现mmap。例如:

windowsize = 8*1024*1024size = os.fstat(f.fileno()).st_sizefor start in range(0, size, window size):    with mmap.mmap(f.fileno(), access=mmap.ACCESS_READ,         length=windowsize, offset=start) as m:        process(m)

当然,如果需要定界,则映射窗口与读取块具有相同的问题,并且可以用相同的方法解决。

但是,作为一种优化,而不是缓冲,您可以将窗口向前滑动到包含最后一条完整消息末尾的页面,而不是一次滑动8MB,然后可以避免任何复制。这有点复杂,因此,如果要执行此 *** 作,请搜索“滑动mmap窗口”之类的内容,并在遇到问题时写一个新问题。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5645989.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存