如何使用二进制、变量查找与foreach优化Perl星期转整数脚本
Perl星期缩写转位掩码脚本优化
需求描述
接收「Mon」「Tue」「Wed、Thu、Sun」这类星期缩写输入,返回对应的整数(位掩码)表示选中的星期组合。
原始实现代码
use strict; use feature qw(signatures); use warnings; no warnings qw(experimental::signatures); my $DAYS_OF_WEEK_LOOKUP = ( { mon => 1, tue => 2, wed => 4, thu => 8, fri => 16, sat => 32, sun => 64 }); my $days_of_week_integer= days_of_week_to_int (['zzz', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'fri', 'SAT']); print "$days_of_week_integer\n"; sub days_of_week_to_int ($days) { my $day_of_week = 0; foreach my $key (@$days) { $day_of_week += $DAYS_OF_WEEK_LOOKUP->{lc($key)} if $DAYS_OF_WEEK_LOOKUP->{lc($key)}; } return $day_of_week if $day_of_week < 128; return; }
核心优化点
- 查找表改用普通哈希存储,减少哈希引用的一层解引用开销
- 查找表通过
map动态生成,避免手动赋值写错位值,后续调整星期顺序也更易维护 - 使用位异或(
^=)替代加法计算位掩码,更符合位操作的场景特性,就算输入重复星期也不会出错 - 直接传入数组引用作为参数,避免数组整体拷贝的性能损耗
- 去掉冗余的范围判断,7位的位掩码最大值就是127,不可能超过128
优化后代码与基准测试
测试对比代码
use strict; use Benchmark ':all'; my $polar_bitmap = 0x01; my @polar_days_of_week = qw/Mon Tue Wed Thu Fri Sat Sun/; # USA/Canada week days order my $orig_DAYS_OF_WEEK_LOOKUP = ( { Mon => 1, Tue => 2, Wed => 4, Thu => 8, Fri => 16, Sat => 32, Sun => 64 }); my %polar_DAYS_OF_WEEK_LOOKUP = map { $_ => ( $polar_bitmap <<= 1 ) / 2 } @polar_days_of_week; my @days; @days = qw/Mon Wed Tue Sat Sun Thu/; print "orig : " . (orig_days_of_week_to_int(@days)) . "\n"; print "polar : " . (polar_days_to_mask ( \@days)) . "\n"; @days = qw/Mon Sat Sun Thu/; print "polar : " . (polar_days_to_mask(\@days)) . "\n"; print "orig : " . (orig_days_of_week_to_int(@days)) . "\n"; @days = qw/Mon Wed Tue Sat Sun Thu/; cmpthese(-3, { orginal => sub { orig_days_of_week_to_int(@days) }, polar_b => sub { polar_days_to_mask(\@days) }, }); exit 0; sub polar_days_to_mask { my $days = shift; my $mask; $mask ^= $polar_DAYS_OF_WEEK_LOOKUP{$_} for @$days; return $mask; } sub orig_days_of_week_to_int { my @days = @_; my $day_of_week = 0; foreach my $key (@days) { $day_of_week += $orig_DAYS_OF_WEEK_LOOKUP->{$key}; } return $day_of_week; }
测试结果
家用HP裸金属设备测试输出
orig : 111 polar : 111 polar : 105 orig : 105 Rate orginal polar_b orginal 1411082/s -- -41% polar_b 2398719/s 70% --
Linode节点测试输出
Rate orginal polar_b orginal 741061/s -- -25% polar_b 992490/s 34% --
性能结论
优化版本在家用设备上性能提升70%,Linode节点上性能提升34%,基准测试结果会受硬件差异影响,但优化效果显著。
内容的提问来源于stack exchange,提问作者Mark Arnold
相关产品推荐
相关产品推荐

