5

我刚刚将 2 台机器从 Fedora 31 升级到 33,通过升级,Perl 从 5.30.3 升级到 5.32.1。

我注意到的第一件事是 GDBM_File.pm 不再包含在 Perl Core 中,但这没问题。

我注意到的第二件事是在 fc33/perl5.32.1 中写入 GDBM非常慢。那是个问题。

我注意到第一台机器上有些问题,所以在升级之前我在第二台机器上用 fc31/perl5.30.3 运行了一个小基准测试。

gdbm1.pl 正在从一个 ascii 文本文件重建一个 db 文件,大约 33M 条目。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 快。但是 gdbm0 和 gdbm1 唯一的差异是写入数据库,所以时间差异都是由于这个原因。在 fc31/perl5.30.3 上,该差异低于 7m。在 fc33/perl5.32.1 上,时间差异是惊人的 550m - 超过 9 小时,而之前是 7 分钟。

我已经在 perl5.32.1 中搜索了有关 GDBM_File 缓慢的任何内容,但我什么也没找到。我什至不知道 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

我在每台机器上运行了两个基准测试,首先使用内存内哈希,然后使用 gdbm 哈希。内存中的哈希结果给出了每台机器的相对单线程性能的一个非常粗略的概念:

[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 天前提交了一个错误,并且已经有一个已签入的修复程序和待发布的版本。

@davem 完全正确,问题不在于 Perl 本身,而在于底层的 gdbm 库。从修复提交评论:

“提交 4fb2326a4a 引入了内存映射区域的预读取。在加快搜索速度的同时,它对写入操作有负面影响,因为每次重新映射都会有效地重新读取整个数据库。”

4

0 回答 0