原創博客,轉載請聯繫博主!數組
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倍左右,因此我更推薦後者!