当前位置: 首页 > 面试题库 >

当整个文件太大时,如何在python中使用mmap

乐华晖
2023-03-14
问题内容

我有一个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,因此从性能上来说,它与我映射10MB文件相同吗?

谢谢。


问题答案:

首先,机器的内存是无关紧要的。相关的是进程的
地址空间

的大小。使用32位Python,该文件大小将低于4GB。使用64位Python,将绰绰有余。

这样做的原因mmap不是要将文件映射到物理内存,而是要映射到
虚拟内存
。一个mmapPED文件变得就像为你的程序的特殊的交换文件。考虑这一点可能会有些复杂,但是上面的Wikipedia链接应该会有所帮助。

因此,第一个答案是“使用64位Python”。但显然,这可能不适用于您的情况。

显而易见的替代方法是在前1GB中进行映射,搜索,取消映射,在后1GB中进行映射,依此类推。您可以通过在方法中指定lengthoffset参数来实现此目的mmap。例如:

m = mmap.mmap(f.fileno(), length=1024*1024*1024, offset=1536*1024*1024)

但是,您要搜索的正则表达式可以在前1GB中途找到,而在第二GB中则找到一半。因此,您需要使用窗口化-
在前1GB中映射,搜索,取消映射,然后在部分重叠的1GB中映射,依此类推。

问题是,您需要多少重叠?如果您知道一场比赛的最大可能规模,那么您将不需要什么。而且,如果您不知道……好,那么就没有办法解决您的问题而又不用破坏正则表达式了-
如果这不太明显,请想象一下如何在一个1GB的窗口中找到2GB的匹配项。

回答您的后续问题:

由于我将缓冲区设置为10MB,因此从性能上来说,它与我映射10MB文件相同吗?

与任何性能问题一样,如果它确实很重要,则需要对其进行测试,如果不重要,则不必担心。

如果您想让我猜测:我想mmap这里可能会更快,但这仅仅是因为(正如JF
Sebastian所暗示的那样)re.match频繁循环和调用128K次可能会使您的代码受CPU约束,而不是IO约束。但是您可以无需mmap使用来优化它read。所以,会mmapread?考虑到所涉及的大小,我希望mmap在旧的Unix平台上的性能要快得多,在现代Unix平台上的性能要差不多,而在Windows上的性能要慢一些。(如果使用,您仍然可以mmap通过+readread+获得较大的性能优势,但这在这里并不重要。)但是,实际上,这只是一个猜测。lseek``madvise

使用最引人注目的原因mmap通常是它比read基于代码的代码更简单,而不是更快。当您甚至必须使用窗口时mmap,而当您不需要使用时read,这并不那么引人注目,但是仍然,如果您尝试用两种方式编写代码,我希望您的mmap代码最终会有点更具可读性。(特别是如果您尝试从明显的read解决方案中优化缓冲区副本。)



 类似资料:
  • 问题内容: 这是一个功能代码(成功创建文件) 现在,我尝试使用当前日期/时间来命名文件(我不是Python专家) 我想写出一个具有确切日期和时间的文件名,它是程序已经创建的一个xml文件,我只需要命名该文件即可。上面的代码不起作用。 错误返回: 问题答案: 不使用时,这可以解决您的问题(回答您的问题),该问题是使用您指定的当前时间和日期格式获取字符串: 产量: 因此您的文件名可以追加或使用此字符串

  • 问题内容: 我需要在Go中对int64的较大值执行运算,例如求幂和除法,但是我遇到了溢出问题。我尝试将它们转换为float64,但随后遇到其他问题。这是我尝试过的。 我有一个整数变量,必须将其转换为float64才能使用方便的数学包(https://golang.org/pkg/math)。 但是,如果整数变量太大,则无法正确转换。我假设这是因为大小大于float64。例如: 我正在尝试使用mat

  • 问题内容: 这是我上传多个文件的代码: HTML代码: 密码: 但是它会上传单个文件,而不是多个文件。 问题答案: 在模板中,你需要在上传输入中添加属性: 然后在查看功能中,上传的文件可以通过列表获取。循环此列表并在每个项目上调用save()方法将它们保存在给定路径中: 此外,你可能需要使用secure_filename()来清洁文件名: 你也可以使用此方法生成随机文件名。 完整演示 视图: im

  • 问题内容: 我有一个巨大的文本文件(〜1GB),可惜我使用的文本编辑器无法读取这么大的文件。但是,如果我可以将其分为两部分或三部分,那就没问题了,因此,作为练习,我想用python编写一个程序来做到这一点。 我想让程序执行的操作是找到文件的大小,将该数字分成多个部分,然后对于每个部分,逐块读取至该点,写入 文件名.nnn输出文件,然后读取- 到下一个换行符并将其写入,然后关闭输出文件,等等。显然,

  • 问题内容: 嗨,我很难理解为什么这不起作用 莫尔斯电码只是一串数字。问题是它说Integer number太大:4545454545,但是我确定Long可以更长。 问题答案: 您需要使用或将其限定为。默认情况下,是文字,超出的范围。 建议使用大写字母以避免混淆,因为和看起来很相似 你可以做 : 要么 根据JLS 3.10.1 : 如果整数文字 以ASCII字母L或l(ell) 为后缀,则其类型为l

  • 问题内容: 我在Windows中编写Python脚本。我想根据文件大小做一些事情。例如,如果大小大于0,我将向某人发送电子邮件,否则继续其他操作。 如何检查文件大小? 问题答案: 使用,并使用结果对象的成员: 输出以字节为单位