是否可以在 Perl 中保留哈希表的大小?
Posted
技术标签:
【中文标题】是否可以在 Perl 中保留哈希表的大小?【英文标题】:Is it possible to reserve the size of a hash table in Perl? 【发布时间】:2011-09-30 22:57:35 【问题描述】:我正在 Perl 中创建一个大小未知的哈希表。
哈希表将字符串映射到对数组的引用。
我的应用程序的主循环在每次迭代中向哈希表添加 5-10 个元素。随着哈希表填满,事情开始急剧放缓。根据观察,当哈希表中有大约 50k 个键时,添加键的速度会降低 20 倍。
我假设哈希表已满,并且正在发生冲突。我想“保留”哈希表的大小,但我不确定如何。
有问题的哈希是 hNgramsToWord。
对于每个单词,该单词的 1-len-gram 作为键添加,并引用包含该 ngram 的单词数组。
例如:
AddToNgramHash("你好");
[h, e, l, l, o, he, el, ll, lo, hel, llo, hell, ello, hello ] 都作为键添加,映射到“hello”
sub AddToNgramHash($)
my $word = shift;
my @aNgrams = MakeNgrams($word);
foreach my $ngram (@aNgrams)
my @aWords;
if(defined($hNgramsToWord$ngram))
@aWords = @$hNgramsToWord$ngram;
push (@aWords, $word);
$hNgramsToWord$ngram = \@aWords;
return scalar keys %hNgramsToWord;
sub MakeNgrams($)
my $word = shift;
my $len = length($word);
my @aNgrams;
for(1..$len)
my $ngs = $_;
for(0..$len-$ngs)
my $ngram = substr($word, $_, $ngs);
push (@aNgrams, $ngram);
return @aNgrams;
【问题讨论】:
我的猜测是 perl 根本就没有考虑到类似的东西(那是很多键)。据我所知,在这样的实现中没有任何低级别的访问权限。 @crimson_penguin:不是真的,反正 50k 也不是很多钥匙 【参考方案1】:您可以像这样设置哈希的桶数:
keys(%hash) = 128;
数字将四舍五入为 2 的幂。
也就是说,您看到的减速不太可能是由于过多的哈希冲突造成的,因为 Perl 会根据需要动态扩展存储桶的数量。从 5.8.2 开始,它甚至会检测导致给定存储桶被过度使用的病态数据,并为该哈希重新配置哈希函数。
显示您的代码,我们可能会帮助您找到真正的问题。
大量哈希键的演示(不要让它继续直到你内存不足......):
use strict;
use warnings;
my $start = time();
my %hash;
$SIGALRM = sub
alarm 1;
printf(
"%.0f keys/s; %d keys, %s buckets used\n",
keys(%hash) / (time() - $start),
scalar(keys(%hash)),
scalar(%hash)
);
;
alarm 1;
$hashrand()++ while 1;
一旦有很多键,当它需要扩展存储桶的数量时,您会注意到明显的减速,但它仍然保持相当均匀的速度。
查看您的代码,加载的单词越多,每个单词要做的工作就越多。
你可以通过改变这个来修复它:
my @aWords;
if(defined($hNgramsToWord$ngram))
@aWords = @$hNgramsToWord$ngram;
push (@aWords, $word);
$hNgramsToWord$ngram = \@aWords;
到这里:
push @ $hNgramsToWord$ngram , $word;
无需复制数组两次。无需检查 ngram 是否已经有条目 - 它会为您自动激活数组引用。
【讨论】:
有趣。我已经添加了上面的代码,并将通过设置散列大小进行测试。谢谢。 @user756079:是的,不是哈希冲突的问题 哇。它刚刚运行并在大约 5 秒内完成。是的,你是一位绅士和学者。 @user756079:这会加快速度吗?sub MakeNgrams map $_[0] =~ /(?=(.$_))/g, 1..length $_[0]
以上是关于是否可以在 Perl 中保留哈希表的大小?的主要内容,如果未能解决你的问题,请参考以下文章