Skip to content

Instantly share code, notes, and snippets.

@Digital-Daz
Created August 8, 2022 12:39
Show Gist options
  • Save Digital-Daz/1754aa73c5f8c3c3dfce1b680012bf4b to your computer and use it in GitHub Desktop.
Save Digital-Daz/1754aa73c5f8c3c3dfce1b680012bf4b to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
#########################################################
# multitest, by Marcus Sorensen, BetterServers Inc #
# Licensed under the Open Software License version 3.0 #
# http://opensource.org/licenses/OSL-3.0 #
#########################################################
use strict;
$| = 1;
my $colors = { red => "\e[1;31m", def => "\e[0m", green => "\e[1;32m", cyan => "\e[1;36m" };
my $restbetweentests = 15;
unless ( `which fio 2>/dev/null`) {
print "No executable 'fio' found in path, exiting\n";
exit;
}
print <<EOF;
$colors->{red}
Multiple IO Tester$colors->{def}
This application emulates a busy server in several states by launching multiple
threads that do various types of IO. This allows us to see what the consequences
are of running in a multitasking environment. This test uses direct IO and
invalidates caches between tests, testing the disk, not the memory.
$colors->{red}NOTE:$colors->{def} You need at least 3GB of free space in your current working directory.
The following tests currently consist of:
8 sequential readers
8 sequential writers
8 mixed seqential readers/writers (random choice per IO)
8 random readers
8 random writers
8 mixed random readers/writers (random choice per IO)
Feel free to modify the script to meet your needs. Enjoy!
The test should take less than 2 minutes. Press <ENTER> to begin...
EOF
<STDIN>;
my $tests = { 'read' => { 'order' => 1,
'block' => '1024k',
'output' => { 'multiiotester'=>'4', '2'=>'5', '3'=>'6' },
'name' => 'sequential read' },
'write' => { 'order' => 2,
'block' => '1024k',
'output' => { 'multiiotester'=>'20', '2'=>'25', '3'=>'47' },
'name' => 'sequential write' },
'rw' => { 'order' => 3,
'block' => '1024k',
'output' => { 'multiiotester'=>'4,20', '2'=>'5,25', '3'=>'6,47' },
'name' => 'seq read/seq write' },
'randread' => { 'order' => 4,
'block' => '4k',
'output' => { 'multiiotester'=>'4', '2'=>'5', '3'=>'6' },
'name' => 'random read' },
'randwrite' => { 'order' => 5,
'block' => '4k',
'output' => { 'multiiotester'=>'20', '2'=>'25', '3'=>'47' },
'name' => 'random write' } ,
'randrw' => { 'order' => 6,
'block' => '4k',
'output' => { 'multiiotester'=>'4,20', '2'=>'5,25', '3'=>'6,47' },
'name' => 'rand read/rand write' }
};
#mkdir('./multiiotester') or die "unable to create test directory: $^E";
mkdir('./multiiotester') if ! -d './multiiotester';
chdir('./multiiotester') or die "unable to chdir to test directory: $^E";
foreach my $t ( sort{$tests->{$a}->{order} cmp $tests->{$b}->{order}} keys %{$tests} ) {
print "$colors->{cyan} running IO \"$tests->{$t}->{name}\" test... $colors->{def}\n";
my $cmd = "fio --direct=1 --invalidate=1 --ioengine=libaio --iodepth=8 --thread --time_based --runtime=10 --rw=$t --bs=$tests->{$t}->{block} --size=300M --numjobs=8 --name=multiiotester --minimal | grep ';'";
my @output = `$cmd`;
$output[0] =~ /^(.*?);/;
my $version = $1;
my $data;
foreach my $d (@output){
next unless $d =~ /;/;
my $field = $tests->{$t}->{output}->{$version};
my @items = split(";",$d);
if ($field =~ /(\d+),(\d+)/) {
$data .= "$items[$1];$items[$2]\n";
} else {
$data .= "$items[$field]\n";
}
}
my @results = split(/;/,combinejobs($data));
my @iops = map { toiops($_,$tests->{$t}->{block}) } @results;
@results = map { convert($_) } @results;
if( $t =~ /^rand/ ) {
print "\tresult is $colors->{green}" . join("/", @results) . "$colors->{def} per second\n";
print "\tequals $colors->{green}" . join("$colors->{def}/$colors->{green}", @iops) . "$colors->{def} IOs per second\n\n";
}
else {
print "\tresult is $colors->{green}" . join("$colors->{def}/$colors->{green}", @results) . "$colors->{def} per second\n\n";
}
sleep $restbetweentests;
}
#print "cleaning up files..\n";
#unlink glob "multiiotester*";
#chdir("..");
#rmdir("multiiotester") or print "unable to delete directory 'multiiotester'\n";
###########################
####### subroutines #######
###########################
sub convert {
my $val = shift;
my @units = ('KB','MB','GB');
my $i = 0;
$val =~ /^\d+/;
while (length($&) > 3 ) {
$val = sprintf("%.2f",$val / 1024);
$i++;
$val =~ /^\d+/;
}
return $val . $units[$i];
}
sub toiops {
my $val = shift;
my $blocksize = shift;
$blocksize =~ s/k//;
my $io = sprintf("%.1f",$val/$blocksize);
return $io;
}
sub combinejobs {
my $input = shift;
my @lines = split(/\n/,$input);
my @output = ();
foreach my $l (0..$#lines) {
my @temp = split(/;/,$lines[$l]);
foreach my $t (0..$#temp){
$output[$t] += $temp[$t];
}
}
return join(";",@output);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment