我有一个python脚本,它逐行读取一个文件,并查看每一行是否与正则表达式匹配。
我想通过在搜索之前使用内存映射文件来提高该脚本的性能。我已经研究了mmap示例:http://docs.python.org/2/library/mmap.html
我的问题是,当文件太大(15GB)而无法存储我的计算机(4GB)时,我如何才能命令它
我读了这个文件:
fi = open(log_file, 'r', buffering=10*1024*1024)
for line in fi:
//do somemthong
fi.close()
由于我将缓冲区设置为10MB,在性能方面,它是否与MMAP10MB文件相同?
谢谢你。
我是来尝试使用
mmap
的,因为我在一个大小为几十GB的文件上使用了fileh.readline()
,并希望使它更快。Unixstrace
实用程序似乎揭示了文件现在是以4kB的块读取的,至少strace的输出在我看来打印得很慢,我知道解析文件需要很多小时。到目前为止,这个线程是唯一解释我不应该试图
mmap
一个太大的文件的原因。我不明白为什么还没有像mmap_for_dummies(filename)
这样的帮助函数,它可以在os.path.size(filename)内部执行,然后执行普通的open(filename, 'r', buffering=10*1024*1024)
或执行mmap.mmap(open(filename).fileno())
。我当然想避免自己修改滑动窗口方法,但是函数是否做一个简单的决定,是否做mmap
对我来说就足够了。最后要提的是,我仍然不清楚为什么互联网上的一些例子没有解释就提到
open(filename, 'rb')
(例如https://docs.python.org/2/library/mmap.html)。如果有人经常想在for循环中使用带有.readline()
调用的文件,我不知道是应该以'rb'
模式打开还是只以'r'
模式打开(我想有必要保留'\n'
)。感谢您提到
buffering=10*1024*1024)
参数,这可能比更改代码以获得某种速度更有帮助。首先,你机器的记忆无关紧要。与此相关的是进程的大小address space。如果是32位的Python,它的容量将低于4GB。有了64位的Python,就足够了。
原因是^{} 不是mapping a file进入物理内存,而是virtual memory。一个
mmap
ped文件就像程序的一个特殊交换文件。考虑这个问题可能会有点复杂,但上面的维基百科链接应该会有所帮助。所以,第一个答案是“使用64位Python”。但很明显,这可能不适用于你的情况。
最明显的替代方法是在第一个1GB中映射、搜索、取消映射、在下一个1GB中映射等等。这样做的方法是将
length
和offset
参数指定给mmap
方法。例如:但是,您正在搜索的regex可能在前1GB中找到一半,在后1GB中找到一半。因此,您需要在第一个1GB中使用窗口映射,搜索、取消映射,然后在部分重叠的1GB中映射,等等
问题是,你需要多少重叠?如果你知道一个匹配的最大可能大小,你不需要比这更多的东西。如果你不知道…好吧,那么没有办法真正解决这个问题,而不打破你的正则表达式如果这不是显而易见的,想象一下,你怎么可能找到一个2GB匹配在一个1GB的窗口。
回答你的后续问题:
对于任何性能问题,如果它真的很重要,您需要测试它,如果它不重要,不要担心它。
如果你想让我猜猜:我认为
mmap
在这里可能更快,但这仅仅是因为(正如J.F.Sebastian所暗示的那样)循环和调用re.match
128K次的频率可能会导致你的代码被CPU绑定而不是IO绑定。但是你可以不用mmap
来优化它,只要使用read
。那么,mmap
会比read
快吗?考虑到所涉及的大小,我预计mmap
的性能在旧的Unix平台上会快得多,在现代的Unix平台上也差不多,在Windows上会慢得多。(如果您使用的是madvise
,您仍然可以从mmap
中获得比read
或read
+lseek
更大的性能优势,但这与此处无关。)但实际上,这只是一个猜测。使用
mmap
最令人信服的原因通常是它比基于read
的代码简单,而不是更快。当你不得不使用视窗甚至是mmap
时,当你不需要用read
进行任何搜索时,这就不那么令人信服了,但是,如果你尝试用两种方式编写代码,我希望你的mmap
代码最终会更可读一些。(尤其是当您试图从明显的read
解决方案中优化缓冲区副本时。)相关问题 更多 >
编程相关推荐