大量データの分割、切り出し処理
スクリプトで大量のデータ処理をしていてsplitが重いと感じたので
色々比較してみた。perlのsplitは正規表現での分割なので、そんなに早くは
無いだろうと思ったが、書き方によっても結構違うようだ。
対象データは300万行、600MB程度。
行単位で読み込んで該当フィールドのみを切り出して変数に格納。
以下、ループ内の処理だけ記述。
- splitその1 所要時間20.0sec
@list = split(/: /,$_); $result = $list[1];
- splitその2 所要時間11.5sec
$result = (split(/: /,$_))[1];
- 正規表現その1 所要時間9.6sec
$_ =~ /: (\w+?):/; $result = $1;
- 正規表現その2 所要時間16.9sec
$_ =~ /.*: (\w+?):.*/; $result = $1;
- index+substr 所要時間7.0sec
$pos1 = index($_,']: '); $pos1 += 3; $pos2 = index($_,': ',$pos1); $result = substr($_,$pos1,$pos2 - $pos1);
- substrのみ 所要時間4.4sec
#オフセットがずれると破綻 $result = substr($_,16,12);
- 正規表現(複数)その1 所要時間12.3sec
$_ =~ /: (\w+?): .*?hoge=(.+?) /; $result1 = $1; $result2 = $2;
- 正規表現(複数)その2 所要時間16.4sec
$_ =~ /: (\w+?): /; $result1 = $1; $_ =~ /hoge=(.+?) /; $result2 = $1;
- index+substr(複数) 所要時間10.7sec
$pos1 = index($_,']: '); $pos1 += 3; $pos2 = index($_,': ',$pos1); $result1 = substr($_,$pos1,$pos2 - $pos1); $pos1 = index($_,'hoge=',$pos2); $pos1 += 5; $pos2 = index($_,' ',$pos1); $result2 = substr($_,$pos1,$pos2 - $pos1);
全データを分割して格納するような場合には、splitせざる得ないが
部分的に必要なだけの場合は、正規表現やindex+substrで切り出す方が
効率が良い様だ。正規表現も書き方さえ間違わなければそれほど遅くはならない。
切り出す対象が複数の場合も同様でindex+substrの方が早い。
対象の位置関係がはっきりしている場合は、探索位置が明示できる為
複数でも1回の正規表現マッチで行った方が効率が良い。
splitした場合でも、リストへの格納を避けて直接該当要素のみ
取り出せば多少は効率が良い。