原创博客,转载请联系博主!数组
perl里的数据都是以双精度为单元存储的,也就是至关于C/Cpp中的double型,而正则的解析是由perl内置的正则引擎完成的,那么除了重写一个属于本身的排序方法以外,咱们应该怎么作才能加速perl内置的sort方法呢,在下文中你将学到两种前沿的hack级perl排序:网络
(下面示例中将用到的数据的产生方法以下所示)socket
my $cnt=0; my @arr; while($cnt<1000000){ my $key=rand(100000); my $val=rand(100000); my $tmp=$key."#".$val; push @arr,$tmp; #print $tmp."\n"; $cnt++; }
(1)Schwatzian变换:测试
使用能起到加速做用的最佳条件:spa
1. sort比较代码块中要进行正则匹配捕获指针
2. sort比较代码块中要进行解/取引用的操做(尤为是解引用)code
Schwatzian变换的加速思路是将可能会重置重叠进行的正则匹配捕获操做和对象的解和取操做,提早使用一次map完成,而且将捕获的结果放入一个匿名数组/哈希引用之中,那么在sort的比较块中咱们须要作的就是直接在这个匿名数组/哈希中取出提早捕获好的待比较的数据。示例以下所示:orm
my @sorted2=map{$_->[0]} sort{$a->[1]<=>$b->[1]} map{$_=~/\d+.(\d+)/;[$_,$1];}@arr;
(2) Guttman-Rosler变换对象
使用能起到加速做用的最佳条件:blog
1.sort比较代码中要比较的数据长度越长加速效果越明显
Guttman-Rosler变换的思路是用perl中一个特殊的方法pack/unpack,之因此说它特殊,是由于pack/unpack方法是直接由二进制C代码完成的,避开了可能会致使代码速度减慢的perl引擎的数据处理过程。首先具体看一下perl中pack/unpack方法的文档:
Pack 与unpack使用说明: pack可视为将一系列的片断的数值打包在一块儿,可用于对dev档案、socket、memory的读写,由于这些须要一块完整的memory,并且须要事先打包成特定格式,而unpack能够视为将将这些完整的 memory切割计算,取得咱们所须要各部分的Variable。
用法:
pack/unpack “format_def_str” , "original_str"
返回值: 正常是一个标量表明一个pack/unpack后的产生的数据
其中的格式化串的写法/语法以下:
C char
d double
f float
i int
I unsigned int (or unsigned)
l long
L unsigned long
s short
S unsigned short
a : 用空字符(null)补足的字符串
A : 用空格补足的字符串
b : 位串,低位在前
B : 位串,高位在前
c : 带符号字符(一般-128~127)
C : 无符号字符(一般8位)
d : 双精度浮点数
f : 单精度浮点数
h : 十六进制数串,低位在前
H : 十六进制数串,高位在前
i : 带符号整数
I : 无符号整数
l : 带符号长整数
L : 无符号长整数
n : 网络序短整数
N : 网络序长整数
p : 字符串指针
s : 带符号短整数
S : 无符号短整数
u : 转化成uuencode格式
v : VAX序短整数
V : VAX序长整数
x : 一个空字节
X : 回退一个字节
@ : 以空字节(null)填充
首先来看一下perl中Guttman-Rosler变换的示例代码:
my @sorted3=map{ substr $_,4 } sort map { $_=~/\d+#(\d+)/; pack("A*").$_; } @arr;
这一段代码的做用是这样的,首先将本来数组中的每个元素都用pack打包成pack后的格式,以后用一个连缀符“.” 将格式化后的串和本来字符串链接起来,以后的sort的比较代码块忽略不写(也不能写,哪怕是$a<=>$b也会报fetal error),至于这一块sort比较块不写的缘由我真的也就不清楚了,因此说是hack级的写法,这样排序完以后再取出来链接在后面的本来字符串就完成了整个排序的过程!
那么排序的加速结果究竟怎么样呢?我测试的结果是这样的:
其中Schwartzian变换的加速效果会有较大程度的波动,可是Guttman-Rosler变换的加速效果大概稳定在5~20倍左右,因此我更推荐后者!