Mar*_*ahl 10 linux random perl mmap
我正在尝试使用mmap优化大型数据集的处理.数据集在千兆字节范围内.我们的想法是将整个文件映射到内存中,允许多个进程同时处理数据集(只读).但它没有按预期工作.
作为一个简单的测试,我简单地mmap文件(使用perl的Sys :: Mmap模块,使用"mmap"子,我相信它直接映射到底层的C函数)并让进程休眠.执行此操作时,代码在从mmap调用返回之前花费的时间超过一分钟,尽管此测试无效 - 甚至不读取 - 来自mmap的文件.
猜测,我虽然linux可能需要在第一个mmap时读取整个文件,所以在第一个进程中映射文件后(当它正在休眠时),我在另一个尝试读取的过程中调用了一个简单的测试文件的前几兆字节.
令人惊讶的是,似乎第二个进程在从mmap调用返回之前也花费了大量时间,与mmap第一次执行文件的时间大致相同.
我已确保正在使用MAP_SHARED,并且第一次映射文件的进程仍处于活动状态(它尚未终止,并且mmap尚未取消映射).
我期望一个mmapped文件允许我给多个工作进程有效随机访问大文件,但是如果每个mmap调用都需要先读取整个文件,那就更难了.我没有测试使用长时间运行的进程来查看第一次延迟后访问是否很快,但我希望使用MAP_SHARED,另一个单独的进程就足够了.
我的理论是mmap会或多或少地立即返回,并且linux会根据需要或多或少地加载块,但我看到的行为恰恰相反,表明它需要在每次调用mmap时读取整个文件.
知道我做错了什么,或者我是否完全误解了mmap应该如何工作?
Mar*_*ahl 16
好的,发现了问题.正如所怀疑的那样,无论是linux还是perl都不应该受到指责.要打开并访问该文件,我会执行以下操作:
#!/usr/bin/perl
# Create 1 GB file if you do not have one:
# dd if=/dev/urandom of=test.bin bs=1048576 count=1000
use strict; use warnings;
use Sys::Mmap;
open (my $fh, "<test.bin")
|| die "open: $!";
my $t = time;
print STDERR "mmapping.. ";
mmap (my $mh, 0, PROT_READ, MAP_SHARED, $fh)
|| die "mmap: $!";
my $str = unpack ("A1024", substr ($mh, 0, 1024));
print STDERR " ", time-$t, " seconds\nsleeping..";
sleep (60*60);
Run Code Online (Sandbox Code Playgroud)
如果您测试该代码,就没有像我在原始代码中找到的那样的延迟,并且在创建最小样本之后(总是这样做,对!)原因突然变得明显.
错误是我在我的代码中将$mh标量视为句柄,这是一种重量轻且可以轻松移动的东西(读取:按值传递).事实证明,它实际上是一个GB长字符串,绝对不是你想要移动的东西而不创建一个显式引用(perl语言表为"指针"/句柄值).因此,如果您需要以散列或类似方式存储\$mh,请确保存储,并在需要使用它时将其解析${$hash->{mh}},通常作为substr或类似的第一个参数.
| 归档时间: |
|
| 查看次数: |
5819 次 |
| 最近记录: |