#!/bin/bash
#
# vondra_bench.sh, plus a rows loop and a hash_build_sort_mode loop so the
# sorted and unsorted paths run at the same row count and the same
# maintenance_work_mem.  Requires the hash_build_sort_mode patch.
#
# Output columns: persistence type rows mwm sortmode rep ms
#
# Only forced sortmode=on|off is measured, so the code path each build took is
# clear.  A "--- sort on ---" / "--- sort off ---" marker is written ahead of
# each block of rows.  num_buckets comes from pgstathashindex() in $SIZES.
#
# Assumes the server is already running and $DB exists
#
# With --size, only measures index sizes (one build per row count) and skips
# the timed loop entirely.  Sizes do not depend on sortmode or mwm, so this
# is minutes instead of hours.

SIZE_ONLY=0
if [ "${1:-}" == "--size" ]; then
	SIZE_ONLY=1
fi

DB=${DB:-test}
ROWS=${ROWS:-"100000 1000000"}
MWM=${MWM:-"4MB 32MB 128MB"}
REPS=${REPS:-8}
OUT=${OUT:-results_sortmode.csv}
SIZES=${SIZES:-index_sizes.csv}

SIZE_MWM=${SIZE_MWM:-1GB}

psql $DB -q -c "create extension if not exists pgstattuple"

if [ ! -f $SIZES ]; then
	echo "persistence,type,rows,bucket_pages,overflow_pages,bitmap_pages,bytes,pretty" > $SIZES
fi

for l in unlogged logged; do

	for type in int bigint text; do

		for rows in $ROWS; do

			psql $DB -c "drop table if exists t"

			if [ "$l" == "unlogged" ]; then
				psql $DB -c "create unlogged table t (a $type)"
			else
				psql $DB -c "create table t (a $type)"
			fi

			if [ "$type" == "text" ]; then
				psql $DB -c "insert into t select md5(random()::text) from generate_series(1,$rows)"
			else
				psql $DB -c "insert into t select $rows * random() from generate_series(1,$rows)"
			fi

			psql $DB -c "vacuum analyze"

			psql $DB -c "checkpoint"

			#Only done for rep=0.  
			psql $DB -q -c "drop index if exists t_a_idx"
			psql $DB -q -c "set hash_build_sort_mode='on';
			                set maintenance_work_mem='$SIZE_MWM';
			                create index on t using hash (a)"
			psql $DB -tAqF, \
				-c "select '$l','$type',$rows,
				           bucket_pages, overflow_pages, bitmap_pages,
				           pg_relation_size('t_a_idx'),
				           pg_size_pretty(pg_relation_size('t_a_idx'))
				    from pgstathashindex('t_a_idx')" >> $SIZES

			if [ $SIZE_ONLY -eq 1 ]; then
				continue
			fi

			for r in `seq 1 $REPS`; do

				for m in $MWM; do

					for s in on off; do

						echo "--- sort $s --- $l $type rows=$rows mwm=$m rep=$r" >> $OUT

						psql $DB > tmp.log 2>&1 <<EOF
drop index if exists t_a_idx;
set maintenance_work_mem = '$m';
set max_parallel_maintenance_workers = 0;
set hash_build_sort_mode = '$s';
\timing on
create index on t using hash (a);
EOF

						t=`grep '^Time:' tmp.log | tail -1 | awk '{print $2}'`

						echo $l $type $rows $m $s $r $t >> $OUT 2>&1

						psql $DB -c "checkpoint"

					done

				done

			done

		done

	done

done
