2012-05-03 17 views
4

私はPerlで書かれたパーサーで、固定長のファイルを解析しています。レコードの一部は、数字のみで構成された複数の文字列(固定長)で構成されています。文字列の各文字は、ASCII文字ではなく数字としてエンコードされます。つまり、文字列12345がある場合、01 02 03 04 05(31 32 33 34 35の代わりに)としてエンコードされます。Perlでの結合と組み合わせたアンパックの実行

私はunpackでレコードを解析し、この特定の部分は@array = unpack "C44", $sと解凍されています。その後、私は単純な結合で必要な文字列を復旧します($m = join("", @array)のように)。

デコードするのに最適な方法があるのだろうかと思っていました。ファイルは非常に大きく、何百万ものレコードがあります。明らかに、最適化が可能かどうかを調べました。プロファイラは、ほとんどの時間がレコードの解析に費やされていることを示しています(つまり、読み込み、書き込みなどの問題は問題ではありません)。これらの結合によって、ほとんどの時間が解析されます。私は、他のソースから、参加はかなり効率的な操作であることを覚えています。コードの速度を上げることが可能かどうか、また最適なのは何ですか?おそらく、この中間配列を賢明な方法で回避することは可能でしょうか?たとえば、代わりにpack/unpackの組み合わせを使用しますか?

編集:コード例

私はこのようなルックスを最適化しようコード:いつものようにPerlで

while (read(READ, $buf, $rec_l) == $rec_l) { 
     my @s = unpack "A24 C44 H8", $buf; 
     my $msisdn = substr $s[0], 0, 11; 
     my $address = join("", @s[4..14]); 
     my $imsi = join("", @s[25..39]); 
     my $ts = localtime(hex($s[45])); 
    } 

答えて

0

、速くはあり読みにくく:-)

join("", unpack("C44", $s)) 

私はこの変更があなたのコードをスピードアップするとは思わない。すべては、1つのファイル全体を読み込むために結合関数を呼び出す頻度に依存します。チャンクで作業している場合は、それらのサイズを増やしてみてください。アンパックとこの配列への参加の間に何らかの操作を行っているなら、それらをマップ操作で整列させてみてください。ソースコードを投稿すると、ボトルネックを特定するのが容易になります。

+0

質問にさらにコードを追加しました。 – MariusM

0

私はパック/アンパックのnoobだけど、どのようにのようなあなたのサンプルコードを変更することにより、参加スキップについて:

my $m = unpack "H*", $s ; 

簡単なテスト:

#!/usr/bin/perl 

use strict ; 
use Test::More tests => 1 ; 

is(unpack("H*", "\x12\x34\x56"),"123456"); 
6

未テストを(私が来ます私が忙しさが減っているときに編集してください)しかし、これはすべての計算が正しく行われ、より速くなるとうまくいくはずです:

my ($msisdn, $address, $imsi, $ts) = 
    unpack "A11 x13 x3 a10 x10 a15 x5 N", $buf; 
$address |= "0" x 10; 
$imsi |= "0" x 15 
$ts = localtime($ts); 
+0

小さな修正だけが必要でしたが、これは正しいものです。そして私の倍の速さ。このアンパックを調べると、どうやってこれらの結合を思いついたのでしょうか?( – MariusM

+0

@MariusM修正が何であるか教えてもらえれば、私の答えを編集できます。 – hobbs

+1

'hex unpack 'H8''は – ikegami

関連する問題