python - 使用 madvise 加速 python mmap
问题描述
我使用 pythonmmap
相当快地访问非常大文件的随机位置。现在我阅读madvise()
并尝试进一步加快内存映射文件的随机访问。我现在看到的行为令人困惑,所以我请求帮助。我在文件中有一个位置数组(字节偏移),我想在其中读取以下多行。对于这些字节偏移中的每一个,我都会调用mm.madvise(mmap.MADV_WILLNEED, ..)
以告诉内核(?)它们将很快被访问。如果我抓住一条线,这会加快速度。但是,如果我尝试访问多条线路,那么时间就会很奇怪。下面的一些示例代码和时序:
import mmap
import numpy as np
source = "path/to/file"
offsets = np.array([28938058915, 12165253255, 3363686649, 2337907709, 18321471207,
3043986123, 29547707866, 23431772405, 14399201212, 8695070697], dtype="uint64")
def get_data_batch(source, offsets):
# open the big file in byte mode and initiate the mmap
with open(source, 'rb') as f:
mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
pagesize = 4096
# prepare starts sites for madvise call
# start of WILLNEED has to be multiple of pagesize
new_offsets = offsets - (offsets % pagesize)
# tell kernel which positions are needed
for new_offset in new_offsets:
# preload say 20 pages of data following each offset
mm.madvise(mmap.MADV_RANDOM)
mm.madvise(mmap.MADV_WILLNEED, int(new_offset), 20)
# now actually read the data
for offset in offsets:
# Use offset to jump to position in file
mm.seek(offset)
# read several lines at that position
chunk1 = mm.readline()
chunk2 = mm.readline()
chunk3 = mm.readline()
chunk4 = mm.readline()
chunk5 = mm.readline()
chunk6 = mm.readline()
如果我在不使用 的情况下执行该函数madvise()
,我可以看到访问第一行需要相当长的时间,但以下几行非常快:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
...
22 100 1360035.0 13600.4 98.1 chunk1 = mm.readline()
23 100 12004.0 120.0 0.9 chunk2 = mm.readline()
24 100 94.0 0.9 0.0 chunk3 = mm.readline()
25 100 282.0 2.8 0.0 chunk4 = mm.readline()
26 100 63.0 0.6 0.0 chunk5 = mm.readline()
27 100 11785.0 117.8 0.8 chunk6 = mm.readline()
如果我包含madvise()
,我会获得整体加速,并且第一行的阅读速度非常快。但是以下一些现在需要一些时间,尽管要少得多:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
...
22 100 4514.0 45.1 1.7 chunk1 = mm.readline()
23 100 107462.0 1074.6 39.7 chunk2 = mm.readline()
24 100 89.0 0.9 0.0 chunk3 = mm.readline()
25 100 79073.0 790.7 29.2 chunk4 = mm.readline()
26 100 91.0 0.9 0.0 chunk5 = mm.readline()
27 100 71475.0 714.8 26.4 chunk6 = mm.readline()
有人可以解释发生了什么吗?有没有办法让所有readline()
电话都像最快的电话一样快?
谢谢
解决方案
推荐阅读
- android - Android:停止前台服务导致应用程序崩溃
- c# - 动态对象不包含来自引用的属性定义
- vue.js - 在 webcomponent 构建中使用插槽时,VueJS $children 为空
- node.js - 为什么在 Node.js 中使用猫鼬模式
- python - 按行中的值从熊猫数据透视表中过滤
- machine-learning - 尝试调用函数时 Octave 中的错误:第 1 行第 1 列附近未定义
- node.js - Mongoose 全文搜索未正确过滤
- php - 将域从 DO 帐户 droplet 移动到另一个 DO 帐户 droplet
- .net-core - 在 Blazor 中筛选分页列表
- wpf - 从 ClipboardWatcher 绑定数据