[英]When accessing individual characters in a string in Perl, is substr or splitting to an array faster?
我正在编写一个Perl脚本,我需要在其中循环遍历字符串的每个字符。 有很多字符串,每个字符串长100个字符(如果你想知道的话,它们是短的DNA序列)。
所以,它是更快地使用substr
在一个时间,以提取每个字符之一,或者是它更快地split
串入一个数组,然后迭代这个数组?
在我等待答案时,我想我会读到如何在Perl中对事物进行基准测试。
这实际上取决于你对数据做了什么 - 但是,嘿,你的最后一个问题是正确的方向! 不要猜,基准。
Perl为这类东西提供了Benchmark模块,使用它非常简单。 以下是一些示例代码:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(cmpthese);
my $dna;
$dna .= [qw(G A T C)]->[rand 4] for 1 .. 100;
sub frequency_substr {
my $length = length $dna;
my %hist;
for my $pos (0 .. $length) {
$hist{$pos}{substr $dna, $pos, 1} ++;
}
\%hist;
}
sub frequency_split {
my %hist;
my $pos = 0;
for my $char (split //, $dna) {
$hist{$pos ++}{$char} ++;
}
\%hist;
}
sub frequency_regmatch {
my %hist;
while ($dna =~ /(.)/g) {
$hist{pos($dna)}{$1} ++;
}
\%hist;
}
cmpthese(-5, # Run each for at least 5 seconds
{
substr => \&frequency_substr,
split => \&frequency_split,
regex => \&frequency_regmatch
}
);
并得到一个结果:
Rate regex split substr
regex 6254/s -- -26% -32%
split 8421/s 35% -- -9%
substr 9240/s 48% 10% --
原来,substr的速度惊人。 :)
这是我要做的,而不是先尝试在substr
和split
之间做出选择:
#!/usr/bin/perl
use strict; use warnings;
my %dist;
while ( my $s = <> ) {
while ( $s =~ /(.)/g ) {
++ $dist{ pos($s) }{ $1 };
}
}
我的好奇心得到了我的好处。 这是一个基准:
#!/usr/bin/perl
use strict; use warnings;
use Benchmark qw( cmpthese );
my @chars = qw(A C G T);
my @to_split = my @to_substr = my @to_match = map {
join '', map $chars[rand @chars], 1 .. 100
} 1 .. 1_000;
cmpthese -1, {
'split' => \&bench_split,
'substr' => \&bench_substr,
'match' => \&bench_match,
};
sub bench_split {
my %dist;
for my $s ( @to_split ) {
my @s = split //, $s;
for my $i ( 0 .. $#s ) {
++ $dist{ $i }{ $s[$i] };
}
}
}
sub bench_substr {
my %dist;
for my $s ( @to_substr ) {
my $u = length($s) - 1;
for my $i (0 .. $u) {
++ $dist{ $i }{ substr($s, $i, 1) };
}
}
}
sub bench_match {
my %dist;
for my $s ( @to_match ) {
while ( $s =~ /(.)/g ) {
++ $dist{ pos($s) }{ $1 };
}
}
}
输出:
Rate split match substr split 4.93/s -- -31% -65% match 7.11/s 44% -- -49% substr 14.0/s 184% 97% --
我在Mastering Perl中有一个处理这个问题的例子。 你想创建一堆单独的标量,每个标量都带有Perl标量的内存开销,或者将所有内容存储在单个字符串中以减少内存,但可能会做更多的工作。 你说你有很多这些,所以如果你担心记忆,把它们作为单个字符串留下来可能会更好。
掌握Perl还有几章涉及基准测试和分析,如果你对这些很好奇。
以太说要让它先工作,然后再担心其余部分。 部分原因是将操作隐藏在面向任务的界面背后。 一个漂亮的面向对象模块可以为您做到这一点。 如果你不喜欢这种方法,你可以改变它。 但是,更高级别的程序不必更改,因为界面保持不变。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.