使用mmap与popen
我需要快速读取和处理大约40MB的gzipped文本文件,并且希望尽量减少输入输出的开销(因为这些文件还被其他人使用)。到目前为止,我找到的最快的方法是这样的:
def gziplines(fname):
f = Popen(['zcat', fname], stdout=PIPE)
for line in f.stdout:
yield line
然后:
for line in gziplines(filename)
dostuff(line)
但我想尝试的(如果这样更快的话)是这样的:
def gzipmmap(fname):
f = Popen(['zcat', fname], stdout=PIPE)
m = mmap.mmap(f.stdout.fileno(), 0, access=mmap.ACCESS_READ)
return m
可惜的是,当我尝试这样做时,我遇到了这个错误:
>>> m = mmap.mmap(f.stdout.fileno(), 0, access=mmap.ACCESS_READ)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
mmap.error: [Errno 19] No such device
尽管当我尝试:
>>> f.stdout.fileno()
4
所以,我觉得我对这里发生的事情有些基本的误解。 :(
我有两个问题:
1) 使用这个mmap方法是否能更快地将整个文件加载到内存中进行处理?
2) 我该如何实现这个?
非常感谢大家……这里的每个人都已经提供了非常大的帮助!
~Nik2 个回答
1
管道是不能使用内存映射的。
case MAP_PRIVATE:
...
if (!file->f_op || !file->f_op->mmap)
return -ENODEV;
而且管道的文件操作里没有 mmap
这个功能。
4
来自 mmap(2)
的手册页面:
ENODEV The underlying file system of the specified file does not sup- port memory mapping.
你不能对流进行内存映射,只能对真正的文件或者匿名的交换空间进行操作。你需要自己把流中的内容读到内存里。