如何加快Perl处理固定宽度数据的速度?

mar*_*ton 5 optimization perl unpack fixed-width

我们有一个成熟的代码体,可以将文件中的数据加载到数据库中.有几种文件格式; 它们都是固定宽度的字段.

部分代码使用Perl unpack()函数将输入数据中的字段读入包变量.然后,业务逻辑能够以"人类可读"的方式引用这些字段.

在读取文件之前,从格式描述生成文件读取代码一次.

在草图形式中,生成的代码如下所示:

while ( <> ) {

    # Start of generated code.

    # Here we unpack 2 fields, real code does around 200.
    ( $FIELDS::transaction_date, $FIELDS::customer_id ) = unpack q{A8 A20};

    # Some fields have leading space removed
    # Generated code has one line like this per affected field.
    $FIELDS::customer_id =~ s/^\s+//;

    # End of generated code.

    # Then we apply business logic to the data ...
    if ( $FIELDS::transaction_date eq $today ) {
        push @fields, q{something or other};
    }

    # Write to standard format for bulk load to the database.
    print $fh join( '|', @fields ) . q{\n} or die;
}
Run Code Online (Sandbox Code Playgroud)

对代码进行分析后发现,大约35%的时间花在解包和前导空间条带上.剩余时间用于验证和转换数据,以及写入输出文件.

似乎业务逻辑的任何一部分都不占运行时间的1-2%.

问题是 - 我们能否以某种方式从拆包和空间剥离中获得更多的速度?优选地,不必重构所有引用FIELDS包变量的代码.

编辑:

如果它有所作为

$ perl -v
This is perl, v5.8.0 built for PA-RISC1.1
Run Code Online (Sandbox Code Playgroud)

Sat*_*ppy 7

我实际上一遍又一遍地处理这个问题.解包比substr好.

就剥离空间而言,你几乎搞砸了.正则表达式黑客攻击是"官方"的方式.你可以通过改进你的unpack语句来获得一些效率(假设没有数据超过4位数,为什么解压缩字段的完整12位?),但除此之外,解析只是一个皮塔饼

祝你的平面数据好运.令人沮丧的传统垃圾,我多么讨厌它.


Sin*_*nür 1

是的。使用提取substr可能是最快的方法。那是:

\n\n
$FIELDS::transaction_date = substr $_, 0, 8;\n$FIELDS::customer_id      = substr $_, 8, 20;\n
Run Code Online (Sandbox Code Playgroud)\n\n

可能会更快。现在,如果我手写这段代码,我不会放弃unpack,但如果你正在生成代码,你不妨尝试一下并测量一下。

\n\n

另请参阅Perl\xe2\x80\x99s unpack() 比 substr() 更快吗?

\n\n

至于剥离前导空格,s/^\\s+//可能是最快的方法。

\n\n

更新:如果无法运行基准测试,就很难说任何明确的事情。然而,怎么样:

\n\n
my  $x  = substr $_, 0, 8;\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于不需要任何修剪的字段

\n\n
my ($y) = substr($_, 8, 20) =~ /\\A\\s+(.+?)\\s+\\z/;\n
Run Code Online (Sandbox Code Playgroud)\n\n

那些需要修剪?

\n

  • 需要注意的一件事是,解压“A”会“免费”去除尾随空格。 (3认同)