[英]How can I use "map" in "perl" to return a hash reference whose key is looked up from an array reference whose value is looked up from another array?
我已经在 map 上搜索了其他许多 Stack 问题,但是这个要求很特殊,所以我可能无法完全找到我正在寻找的解决方案,或者我认为它确实存在。
这个问题只是关于性能。
作为有限的背景,此代码段用于解码传入令牌,因此它用于每个 web 请求,因此性能至关重要,我知道可以使用“地图”所以想使用它。
这是一个精简但仍然可以正常工作的代码段,我目前正在使用它并且运行良好:
use strict;
use Data::Dumper qw (Dumper);
my $api_token = { array => [ 'user_id', 'session_id', 'expiry' ], max => 3, name => 'session' };
my $token_got = [ 9923232345812112323, 1111323232000000465, 1002323001752323232 ];
my $rt;
for (my $i=0; $i<scalar @{$api_token->{array}}; $i++) {
$rt->{$api_token->{array}->[$i]} = $token_got->[$i];
}
$rt->{type} = $api_token->{name};
print Dumper ($rt) . "\n";
问题是:就性能而言,复制上面的 foreach 语句的绝对最佳 PERL 代码是什么?
看起来你只需要一个 hash切片
my %rt;
@rt{ @{ $api_token->{array} } } = @$token_got;
或者,如果需要 hash 参考
my $rt;
@{ $rt } { @{ $api_token->{array} } } = @$token_got;
或者使用较新的后缀取消引用,在数组和 hash 切片上,也许更好一些
my $rt;
$rt->@{ $api_token->{array}->@* } = @$token_got;
也可以使用List::MoreUtils::mesh并在一个语句中完成
my $rt = { mesh @{ $api_token->{array} }, @$token_got };
或来自同一个库的成对
my $rt = { pairwise { $a, $b } @{ $api_token->{array} }, @$token_got };
这些 go 通过 C 代码如果库安装了List::MoreUtils::XS
。
对以上所有内容进行基准测试,使用问题中的微小数据集(虽然现实?),无论实现mesh
/ pairwise
实现它们的速度都是其他实现的数倍。
在装有 v5.26 的旧笔记本电脑上
Rate use_pair use_mesh use_href use_post use_hash use_pair 373639/s -- -36% -67% -67% -68% use_mesh 580214/s 55% -- -49% -49% -51% use_href 1129422/s 202% 95% -- -1% -5% use_post 1140634/s 205% 97% 1% -- -4% use_hash 1184835/s 217% 104% 5% 4% --
在 v5.36 的服务器上,数字大约是pairwise
的160%--170%
( mesh
比它快一点,与上面类似)
在其他方面,在笔记本电脑上,基于哈希的总是快几个百分点,而在 v5.36 的服务器上,它们都非常接近。 很容易称之为领带。
以下是由 OP 编辑的,他计算了 61% 的加速(见评论)
更改代码:
@rt{ @{ $api_token->{array} } } = @$token_got; ### much faster onliner replaced the loop. @zdim credit
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.