(unnamed)
text/plain
#! /usr/bin/perl
use strict;
use IPC::Open2;
use Time::HiRes qw (gettimeofday tv_interval);
my $tupperpage = 226;
my $large_size = 100000000;
my @time = ();
sub bench {
my ($header, $nprocs, $ntups, $threshold, $ddlcount) = @_;
my @result = ();
my @rds = ();
for (my $ip = 0 ; $ip < $nprocs ; $ip++)
{
pipe(my $rd, my $wr);
$rds[$ip] = $rd;
my $pid = fork();
die "fork failed: $!\n" if ($pid < 0);
if ($pid == 0)
{
close($rd);
my $pid = open2(my $psqlrd, my $psqlwr, "psql postgres > /dev/null");
if ($threshold >= 0) {
print $psqlwr "SET wal_skip_threshold to $threshold;\n";
}
print $psqlwr "DROP TABLE IF EXISTS t$ip;";
print $psqlwr "CREATE TABLE t$ip (a int);\n";
my @st = gettimeofday();
for (my $i = 0 ; $i < $ddlcount ; $i++)
{
print $psqlwr "BEGIN;";
print $psqlwr "TRUNCATE t$ip;";
print $psqlwr "INSERT INTO t$ip (SELECT a FROM generate_series(1, $ntups) a);";
print $psqlwr "COMMIT;";
}
close($psqlwr);
waitpid($pid, 0);
print $wr $ip, " ", 1000 * tv_interval(\@st, [gettimeofday]), "\n";
exit;
}
close($wr);
}
my $rpid;
while (($rpid = wait()) == 0) {}
my $sum = 0;
for (my $ip = 0 ; $ip < $nprocs ; $ip++)
{
my $ret = readline($rds[$ip]);
die "format? $ret\n" if ($ret !~ /^([0-9]+) ([0-9.]+)$/);
$sum += $2;
}
printf "$header: procs $nprocs: time %.0f\n", $sum / $nprocs;
}
sub log10 { return log($_[0]) / log(10); }
# benchmark for wal_level = replica, the third parameter of bench
# doesn't affect
sub bench1
{
my $ddlcount = 5;
$ddlcount = $ARGV[1] if ($#ARGV > 0);
print "benchmark for wal_level = replica\n";
for (my $s = 0 ; $s <= 4 ; $s += 0.25)
{
my $ss = int(10 ** $s);
bench("size $ss", 1, $ss * $tupperpage, 0, $ddlcount);
}
}
# benchmark for wal_level = minimal.
sub bench2
{
my $ddlcount = 5;
$ddlcount = $ARGV[1] if ($#ARGV > 0);
print "benchmark for wal_level = minimal\n";
for (my $s = 0 ; $s <= 4.5 ; $s += 0.25)
{
my $ss = int(10 ** $s);
bench("size $ss: SYNC ", 1, $ss * $tupperpage, 0, $ddlcount);
bench("size $ss: WAL ", 1, $ss * $tupperpage, $large_size, $ddlcount);
}
}
# find crossing point of WAL and SYNC by bisecting
sub bench3
{
my $ddlcount = 5;
$ddlcount = $ARGV[1] if ($#ARGV > 0);
print "find crossing point of WAL and SYNC by bisecting\n";
bench("SYNC: size 0", 1, 1, 8);
bench("WAL : size 0", 1, 1, 16);
my $s = 1;
my $st = 10000;
while (1)
{
my $ts = bench("SYNC: size $s",
$tupperpage * $s, 0, $ddlcount);
my $tw = bench("WAL : size $s",
$tupperpage * $s, $large_size, $ddlcount);
if ($st < 1.0){
print "DONE\n";
exit(0);
}
if ($ts > $tw)
{
$s += $st; $st /= 2;
}
else
{
$s -= $st; $st /= 2;
}
}
}
# benchmark with multiple processes
sub bench4
{
my $ddlcount = 5;
my $nprocs = 10;
$nprocs = $ARGV[1] if ($#ARGV > 0);
$ddlcount = $ARGV[2] if ($#ARGV > 1);
print "benchmark for wal_level = minimal, $nprocs processes\n";
print "bench 4: nprocs = $nprocs, DDL count = $ddlcount\n";
for (my $s = 1.0 ; $s <= 3.5 ; $s += 0.25)
{
my $ss = int(10 ** $s);
bench("pages $ss: SYNC ", $nprocs, $ss * $tupperpage, 0, 5);
bench("pages $ss: WAL ", $nprocs, $ss * $tupperpage, $large_size, 5);
}
}
sub bench5
{
my $ddlcount = 5;
my $pages = 100;
my $mode = "s";
my $threshold = 0;
$ddlcount = $ARGV[1] if ($#ARGV > 0);
$pages = $ARGV[2] if ($#ARGV > 1);
$mode = $ARGV[3] if ($#ARGV > 2);
if ($mode eq 's') {
$threshold = 0;
} elsif ($mode eq 's') {
$threshold = $large_size;
} elsif ($mode eq 'n') {
$threshold = -1;
} elsif ($mode eq 'w') {
$threshold = $large_size;
} else {
die "mode must be s, w or n\n";
}
print "bench 5: mode = $mode, DDL count = $ddlcount, pages = $pages\n";
bench("size $pages", 1, $pages * $tupperpage, $threshold, $ddlcount);
}
bench1() if ($ARGV[0] == 1);
bench2() if ($ARGV[0] == 2);
bench3() if ($ARGV[0] == 3);
bench4() if ($ARGV[0] == 4);
bench5() if ($ARGV[0] == 5);