如何解决Perl 5.32.1 GDBM_File 非常慢
我刚刚将 2 台机器从 Fedora 31 升级到 33,通过升级,Perl 从 5.30.3 升级到 5.32.1。
我注意到的第一件事是 GDBM_File.pm 不再包含在 Perl 核心中,但这没问题。
我注意到的第二件事是在 fc33/perl5.32.1 中写入 GDBM 的速度难以置信。这是个问题。
我注意到第一台机器上有些不对劲,所以在升级之前,我在第二台机器上用 fc31/perl5.30.3 运行了一些基准测试。
gdbm1.pl 正在从一个 ascii 文本文件重建一个 db 文件,大约有 3300 万个条目。 gdbm0.pl 正在读取相同的 ascii 文本文件,并执行与 gdbm1.pl 完全相同的所有操作,除了不执行实际的哈希赋值“$db{...} = ...”。这是唯一的不同。 (ascii 文件大约 11GB。)
FC31/Perl5.30.3:
[259] time ./gdbm0.pl 16
real 4m51.593s
user 4m49.808s
sys 0m1.306s
[260] time ./gdbm1.pl 16
real 11m39.682s
user 6m30.619s
sys 3m19.260s
FC33/Perl5.32.1:
[287] time ./gdbm0.pl 16
real 5m10.379s
user 5m8.764s
sys 0m1.299s
[288] time ./gdbm1.pl 16
real 554m48.187s
user 7m49.315s
sys 433m42.435s
显然,写入数据库比不写入需要更长的时间:我一直希望 gdbm0.pl 比 gdbm1.pl 更快。但是唯一的差异 btwn gdbm0 和 gdbm1 正在写入数据库,所以时间差异都是由于这个原因。在 fc31/perl5.30.3 上,该差异小于 7m。在 fc33/perl5.32.1 上,时间差异是惊人的 550m - 超过 9 小时,而之前为 7 分钟。
我在网上搜索了一些关于 GDBM_File 在 perl5.32.1 中运行缓慢的问题,但一无所获。我什至不知道 Perl 是否有问题,可能是 fc33 或两者的某种组合。
或者可能是 fc33 中缺少某些 C 库,而 GDBM_File 正在本机 perl 中执行所有操作。我不知道从这里去哪里。
更新:
@davem:好的,我有 3 台机器:a、b、c。 “a”是最旧和最慢的,“c”是最新和最快的。机器“a”运行ubuntu,另外两个都运行fedora:
Linux a 5.8.0-50-generic #56~20.04.1-Ubuntu SMP Mon Apr 12 21:46:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Linux b 5.11.18-200.fc33.x86_64 #1 SMP Mon May 3 15:05:29 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Linux c 5.11.18-200.fc33.x86_64 #1 SMP Mon May 3 15:05:29 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
我在每台机器上运行了两个基准测试,首先使用 in-mem 哈希,然后使用 gdbm 哈希。 in-mem 哈希结果非常粗略地了解了每台机器的相对单线程性能:
[mem] time perl -e'my %h; $h{$_} = 1 for ("a" .. "zzzzz"); print "@{[scalar(keys(%h))]}\n";'
[gdbm] time perl -e'use GDBM_File; my ($h,%h); $h = "gdbm_write_test"; tie(%h,"GDBM_File",$h,GDBM_NEWDB,0600); $h{$_} = 1 for ("a" .. "zzzzz"); print "@{[scalar(keys(%h))]}\n"; untie(%h);'
machine_a:
[mem] 12356630
real 0m29.051s
user 0m27.975s
sys 0m0.995s
[gdbm] 12356630
real 4m5.431s
user 2m2.033s
sys 1m36.209s
machine_b:
[mem] 12356630
real 0m12.101s
user 0m11.520s
sys 0m0.559s
[gdbm] 12356630
real 106m35.326s
user 1m0.607s
sys 103m48.518s
machine_c:
[mem] 12356630
real 0m9.498s
user 0m9.163s
sys 0m0.317s
[gdbm] 12356630
real 58m46.555s
user 0m39.566s
sys 48m16.447s
更新 2:
我花了一段时间摆弄 Perl-DB_File 和 Perl-BerkeleyDB 作为 Perl-GDBM_File 的可能替代品。因为我懒得去弄清楚如何提交错误。
当然是虚假的懒惰。我终于在 2 天前提交了 a bug,并且已经有 a fix 签入并等待发布。
@davem 完全正确,问题不是 Perl 本身,而是底层的 gdbm 库。来自修复提交评论:
"Commit 4fb2326a4a 引入预读内存映射 地区。在加快搜索速度的同时,也会产生负面影响 在写操作上,因为每次重新映射都会有效地重新读取 整个数据库。”
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。