Benchmark Debug Perl

today we want to take a look whats the fastest way to debug our code in Perl:

#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(:all) ;

use constant {
DEBUG1 => 1,
DEBUG2 => 0
};

my $DEBUG1 = 1;
my $DEBUG2 = 0;
 
cmpthese(-10, {
'if_constant' 	=> sub {if(DEBUG1){print "";}print ""; },
'if_var' 	=> sub {if($DEBUG1){print "";}print ""; },
'and_constant' 	=> sub {DEBUG1 and print "";print "";},
'and_var' 	=> sub {$DEBUG1 and print "";print "";},
});

print $/;

cmpthese(-10, {
'if_constant' 	=> sub {if(DEBUG2){print "";}print ""; },
'if_var' 	=> sub {if($DEBUG2){print "";}print ""; },
'and_constant' 	=> sub {DEBUG2 and print "";print "";},
'and_var' 	=> sub {$DEBUG2 and print "";print "";},
});

and the Benchmark result is this:

                  Rate      and_var  if_constant       if_var and_constant
and_var      6347385/s           --          -7%          -9%         -25%
if_constant  6814160/s           7%           --          -3%         -19%
if_var       7008445/s          10%           3%           --         -17%
and_constant 8427633/s          33%          24%          20%           --

                   Rate      and_var       if_var  if_constant and_constant
and_var       8482773/s           --         -17%         -28%         -37%
if_var       10257262/s          21%           --         -13%         -24%
if_constant  11838939/s          40%          15%           --         -12%
and_constant 13490170/s          59%          32%          14%           --

We see that the best solution in both ways is to use a constant with “and”.It seems to me the compiler remove the constant and the print, becaus if you dont have the print after the command it ends in a infinite loop.

Benchmark Bash fastest replace with tr sed awk perl

Test String (10xX):

___XXXXX_____XXXXX_____

Test Cases Results must look like:

single char remove:

___XXXX_____XXXXX_____

single char replace:

___0XXXX_____XXXXX_____

string/multi char remove:

_____________

string/multi char replace:

___00000_____00000_____

Times:

run the test string from file 100000 times.

single char remove single char replace multi char remove multi char replace string remove string replace
sed 5.658s 5.774s 3.449s 5.929s 3.476s 5.724s
perl regex 5.604s 5.918s 3.428s 6.027s 3.482s 5.870s
awk gsub 3.469s 5.892s 3.339s 5.942s
tr bash 5.972s 5.897s
perl tr  5.996s  5.837s

 

For bash its the easiest way to use sed because its simpler to use perl and it could do the most things or if you do simple things you could use tr.In perl you could see this benchmark.

SED 4.2.2

single char remove:

time cat bench.txt | sed 's/X//'

single char replace:

time cat bench.txt | sed 's/X/0/'

multi char remove:

time cat bench.txt | sed 's/X//g'

multi char replace:

time cat bench.txt | sed 's/X/0/g'

string remove:

time cat bench.txt | sed 's/XXXXX//g'

string replace:

time cat bench.txt | sed 's/XXXXX/00000/g'

 

AWK 4.0.1

single replace with regex not possible.

multi char remove:

time cat bench.txt | awk '{gsub("X","",$1);print $1;}'

multi char replace:

time cat bench.txt | awk '{gsub("X","0",$1);print $1;}'

string remove:

time cat bench.txt | awk '{gsub("XXXXX","",$1);print $1;}'

string replace:

time cat bench.txt | awk '{gsub("XXXXX","00000",$1);print $1;}'

 

TR 8.21

single replace and remove not possible.

multi char replace:

time cat bench.txt | tr "X" "0"

string replace:

time cat bench.txt | tr "XXXXX" "00000"

 

PERL REGEX 5

single char remove:

time cat bench.txt | perl -lpe 's/X//'

single char replace:

time cat bench.txt | perl -lpe 's/X/0/'

multi char remove:

time cat bench.txt | perl -lpe 's/X//g'

multi char replace:

time cat bench.txt | perl -lpe 's/X/0/g'

string remove:

time cat bench.txt | perl -lpe 's/XXXXX//g'

string replace:

time cat bench.txt | perl -lpe 's/XXXXX/00000/g'

 

PERL TR 5

multi char replace:

time cat bench.txt | perl -lpe 's/X/0/g'

string replace:

time cat bench.txt | perl -lpe 's/XXXXX/00000/g'

 

Benchmark Your System (CPU, HDD, RAM) with sysbench/hdparm

At first install sysbench :

apt-get install sysbench hdparm

 

CPU

for CPU bench run :

sysbench --test=cpu --num-threads=8 --cpu-max-prime=20000 run

Result:

Maximum prime number checked in CPU test: 20000


Test execution summary:
    total time:                          3.5538s
    total number of events:              10000
    total time taken by event execution: 28.3796
    per-request statistics:
         min:                                  2.30ms
         avg:                                  2.84ms
         max:                                 31.04ms
         approx.  95 percentile:               3.40ms

Threads fairness:
    events (avg/stddev):           1250.0000/60.13
    execution time (avg/stddev):   3.5474/0.01

 

HDD-Test1

prepare:

sysbench --test=fileio --file-total-size=1G prepare

then test:

sysbench --test=fileio --file-total-size=1G --file-test-mode=rndrw --init-rng=on --max-time=300 --max-requests=0 run

Result:

Operations performed:  40920 Read, 27280 Write, 87270 Other = 155470 Total
Read 639.38Mb  Written 426.25Mb  Total transferred 1.0406Gb  (3.552Mb/sec)
  227.33 Requests/sec executed

Test execution summary:
    total time:                          300.0036s
    total number of events:              68200
    total time taken by event execution: 1.0510
    per-request statistics:
         min:                                  0.00ms
         avg:                                  0.02ms
         max:                                  0.15ms
         approx.  95 percentile:               0.03ms

Threads fairness:
    events (avg/stddev):           68200.0000/0.00
    execution time (avg/stddev):   1.0510/0.00

clean up:

sysbench --test=fileio --file-total-size=1G cleanup

 

HDD-Test2

hdparm -Tt /dev/sda

Result:

/dev/sda:
 Timing cached reads:   7784 MB in  1.99 seconds = 3903.24 MB/sec
 Timing buffered disk reads: 128 MB in  3.01 seconds =  42.54 MB/sec

 

RAM

sysbench --test=memory --memory-block-size=1M --memory-total-size=10G run

Result:

Operations performed: 10240 ( 6368.83 ops/sec)

10240.00 MB transferred (6368.83 MB/sec)


Test execution summary:
    total time:                          1.6078s
    total number of events:              10240
    total time taken by event execution: 1.6057
    per-request statistics:
         min:                                  0.15ms
         avg:                                  0.16ms
         max:                                  0.52ms
         approx.  95 percentile:               0.17ms

Threads fairness:
    events (avg/stddev):           10240.0000/0.00
    execution time (avg/stddev):   1.6057/0.00

Benchmark in Perl – replace

if you want to check whats the fastest way to replace a string in Perl you could use the Benchmark-Module.I compared 4 different ways  :

#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(:all) ;
use Inline 'C';


my $teststring;

#check result :
$teststring = "teststring1"; $teststring =~ s/1/2/g; 				print $teststring.$/;
$teststring = "teststring1"; $teststring =~ s/1/2/go; 				print $teststring.$/;
$teststring = "teststring1"; $teststring =~ tr/1/2/; 				print $teststring.$/;
$teststring = "teststring1"; $teststring = replace($teststring,"1","2"); 	print $teststring.$/;
$teststring = "teststring1"; $teststring = repl_str($teststring,"1","2"); 	print $teststring.$/;

#test one
 cmpthese(-4, {
'regex_normal' 		=> sub {$teststring = "teststring1"; $teststring =~ s/1/2/g; },
'regex_optimised' 	=> sub {$teststring = "teststring1"; $teststring =~ s/1/2/go; },
'translate' 		=> sub {$teststring = "teststring1"; $teststring =~ tr/1/2/; },
'perl_sub' 		=> sub {$teststring = "teststring1"; $teststring = replace($teststring,"1","2"); },
'C_replace_string' 	=> sub {$teststring = "teststring1"; $teststring = repl_str($teststring,"1","2"); },
});


#test two
 cmpthese(-4, {
'regex_normal' 		=> sub {$teststring = "teststring1stringxstring"; $teststring =~ s/string/test/g; },
'regex_optimised' 	=> sub {$teststring = "teststring1stringxstring"; $teststring =~ s/string/test/go; },
'translate' 		=> sub {$teststring = "teststring1stringxstring"; $teststring =~ tr/string/test/; },
'perl_sub' 		=> sub {$teststring = "teststring1stringxstring"; $teststring = replace($teststring,"string","test"); },
'C_replace_string' 	=> sub {$teststring = "teststring1stringxstring"; $teststring = repl_str($teststring,"string","test"); },
});


sub replace {
my $string  = shift;
my $old     = shift;
my $new     = shift;
my $pos     = index($string, $old);
while ( $pos > -1 ) {
 substr( $string, $pos, length( $old ), $new );
 $pos = index( $string, $old, $pos + length( $new ));
}
return($string);
}

__END__
__C__
char* repl_str(const char *str, const char *old, const char *new){
	char *ret, *r;
	const char *p, *q;
	size_t oldlen = strlen(old);
	size_t count, retlen, newlen = strlen(new);

	if (oldlen != newlen) {
		for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen)
			count++;
		retlen = p - str + strlen(p) + count * (newlen - oldlen);
	} else
		retlen = strlen(str);

	if ((ret = malloc(retlen + 1)) == NULL)
		return NULL;

	for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) {
		ptrdiff_t l = q - p;
		memcpy(r, p, l);
		r += l;
		memcpy(r, new, newlen);
		r += newlen;
	}
	strcpy(r, p);

	return ret;
}

the result looks like:

teststring2
teststring2
teststring2
teststring2
teststring2
                      Rate perl_sub C_replace_string regex_normal regex_optimised translate
perl_sub          632214/s       --             -68%         -68%            -70%      -91%
C_replace_string 1961177/s     210%               --          -2%             -8%      -71%
regex_normal     1999403/s     216%               2%           --             -7%      -71%
regex_optimised  2142180/s     239%               9%           7%              --      -69%
translate        6843359/s     982%             249%         242%            219%        --
                      Rate perl_sub regex_normal regex_optimised C_replace_string translate
perl_sub          430150/s       --         -50%            -50%             -57%      -92%
regex_normal      861549/s     100%           --             -0%             -14%      -85%
regex_optimised   862213/s     100%           0%              --             -14%      -85%
C_replace_string  998062/s     132%          16%             16%               --      -82%
translate        5603343/s    1203%         550%            550%             461%        --

Always check you sub results (Line 1-5) and make more test cases,

at the first case (Line 6) we see that for single character the best solution is to use regex.If you want to replace a longer string better use a C function.But in both cases its better to use the /o flag for regex to optimize, but then you cant interpolate a string in to the regex.And if you only want to replaxe use tr its the fastest.