2012-05-03 18 views
4

我有一个用Perl编写的解析器,它解析固定长度记录的文件。部分记录由多个字符串组成(也是固定长度),仅由数字组成。字符串中的每个字符都被编码为数字,而不是ASCII字符。也就是说,如果我有字符串12345,它编码为01 02 03 04 05(而不是31 32 33 34 35)。解压缩结合加入Perl的性能

我用解压解析记录,这个特定部分被解压为@array = unpack "C44", $s。然后我通过简单的连接恢复所需的字符串,如$m = join("", @array)

我想知道如果这是一个最佳的解码方式。文件相当大,数百万条记录,显然我试图查看是否可以优化。 Profiler显示大部分时间都用于解析记录(即读取,写入和其他东西不是问题),并且在解析大部分时间都是由这些连接取得的。我从其他来源记得,加入是非常有效的操作。任何想法,如果有可能加快代码或已经是最佳的?也许有可能以某种聪明的方式避免这个中间数组,例如使用pack/unpack组合呢?

编辑:代码示例

我尝试优化看起来像这样的代码:

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

在Perl与往常一样,更快小于可读:-)

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

我不相信这个改变会加快你的代码。一切都取决于你多久调用一次连接函数来读取整个文件。如果你在分块工作,请尝试增加它们的大小。如果你在解包和加入这个数组之间进行一些操作,尝试将它们与一个映射操作对齐。如果您发布源代码,那么识别瓶颈将更容易。

+0

增加了更多的问题代码。 – MariusM

0

我一包/解包小白,但如何跳过通过改变像这样的示例代码加入:

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''是一个非常迂回的做'解开'N''的方式。固定。 – ikegami