我想知道我们使用的基准测试是否有太多的活动部分:我们正在处理不同大小的数据文件,使用不同的行长度,并试图测量数据传输的速度
tr
相对于它的竞争对手——有一个基本的(但未经检验的)假设
是一种性能随行长变化的方法。
tr公司
总是相同大小(4096字节)的数据缓冲区。如果任何一种方法
对于行大小,应该是
.
我突然想到:如果
tr公司
参考点是否稳定,其他方法是否随管线尺寸而变化?当你从太空船的窗户往外看时,是你还是那只正在移动的克林贡猛禽?
因此,我开发了一个基准测试,使数据文件的大小保持不变:行长度不同,但字节总数保持不变。结果表明:
-
这种方法最不敏感吗
线条长度的变化。自
所有三条线长度的常数
测试(短,中,长),这个
tr公司
编辑给定的字符串。甚至
虽然短线数据文件
tr公司
这种方法能够处理数据
长线文件。
-
<>
速度
随着队伍越来越长,
虽然以递减的速度。这个
<>
需要一些工作,应该是的
使用较短的线条(至少超过
-
这个
s///
方法也是敏感的
到行长度。就像
tr公司
,这个
它是给定的。再短一点的线
长度意味着更多的编辑。显然地,
s码///
这样做
那个
tr公司
.
以下是使用Perl 5.8.8的Solaris上的结果:
# ln = $. <>, then check $.
# nn = $n <>, counting lines
# tr = tr/// using sysread
# ss = s/// using sysread
# S = short lines (50)
# M = medium lines (500)
# L = long lines (5000)
Rate nn-S
nn-S 1.66/s --
ln-S 1.81/s 9%
ss-S 2.45/s 48%
nn-M 4.02/s 142%
ln-M 4.07/s 145%
ln-L 4.65/s 180%
nn-L 4.65/s 180%
ss-M 5.85/s 252%
ss-L 7.04/s 324%
tr-S 7.30/s 339% # tr
tr-L 7.63/s 360% # tr
tr-M 7.69/s 363% # tr
WindowsActiveState的Perl5.10.0上的结果大致相当。
最后,代码:
use strict;
use warnings;
use Set::CrossProduct;
use Benchmark qw(cmpthese);
# Args: file size (in million bytes)
# N of benchmark iterations
# true/false (whether to regenerate files)
#
# My results were run with 50 10 1
main(@ARGV);
sub main {
my ($file_size, $benchmark_n, $regenerate) = @_;
$file_size *= 1000000;
my @file_names = create_files($file_size, $regenerate);
my %methods = (
ln => \&method_ln, # $.
nn => \&method_nn, # $n
tr => \&method_tr, # tr///
ss => \&method_ss, # s///
);
my $combo_iter = Set::CrossProduct->new([ [keys %methods], \@file_names ]);
open my $log_fh, '>', 'log.txt';
my %benchmark_args = map {
my ($m, $f) = @$_;
"$m-$f" => sub { $methods{$m}->($f, $log_fh) }
} $combo_iter->combinations;
cmpthese($benchmark_n, \%benchmark_args);
close $log_fh;
}
sub create_files {
my ($file_size, $regenerate) = @_;
my %line_lengths = (
S => 50,
M => 500,
L => 5000,
);
for my $f (keys %line_lengths){
next if -f $f and not $regenerate;
create_file($f, $line_lengths{$f}, $file_size);
}
return keys %line_lengths;
}
sub create_file {
my ($file_name, $line_length, $file_size) = @_;
my $n_lines = int($file_size / $line_length);
warn "Generating $file_name with $n_lines lines\n";
my $line = 'a' x ($line_length - 1);
chop $line if $^O eq 'MSWin32';
open(my $fh, '>', $file_name) or die $!;
print $fh $line, "\n" for 1 .. $n_lines;
close $fh;
}
sub method_nn {
my ($data_file, $log_fh) = @_;
open my $data_fh, '<', $data_file;
my $n = 0;
$n ++ while <$data_fh>;
print $log_fh "$data_file \$n $n\n";
close $data_fh;
}
sub method_ln {
my ($data_file, $log_fh) = @_;
open my $data_fh, '<', $data_file;
1 while <$data_fh>;
print $log_fh "$data_file \$. $.\n";
close $data_fh;
}
sub method_tr {
my ($data_file, $log_fh) = @_;
open my $data_fh, '<', $data_file;
my $n = 0;
my $buffer;
while (sysread $data_fh, $buffer, 4096) {
$n += ($buffer =~ tr/\n//);
}
print $log_fh "$data_file tr $n\n";
close $data_fh;
}
sub method_ss {
my ($data_file, $log_fh) = @_;
open my $data_fh, '<', $data_file;
my $n = 0;
my $buffer;
while (sysread $data_fh, $buffer, 4096) {
$n += ($buffer =~ s/\n//g);
}
print $log_fh "$data_file s/ $n\n";
close $data_fh;
}
我尝试了所有三种变体,它们的行为大致类似于
s/\n//g
--对于行较短的数据文件,速度较慢(具有
s/(\n)/$1/
比其他人都慢)。有趣的是
m/\n/g
s/\n//g公司
,这表明regex方法的缓慢(两者都是
s码///
m//
)不直接取决于
编辑
绳子。