#!/bin/bash

# Copyright (c)2004-2022 René Rebe

. ./functions

error() {
	echo "ERROR, check last log : $log"
	exit 1
}

trap error ERR

j="$(nproc 2>/dev/null || true)"
j=${j:-1}
sleep="sleep 1" # e.g. 15..30 re therm. throtlling
DATADIR=$PWD/data/
DOWNLOADDIR=$PWD/../download/

timefmt=%e # TODO: or %U + %S

mkdir -p logs
mkdir -p $DATADIR

if [ "$1" ]; then
	name="$1"
	shift
else
	echo "first argument needs to be a results name specification!"
	exit
fi

if [ ! "$1" ]; then
	echo "no benchmark specified ..."
	exit
fi

size () {
	echo "$(du -cb $* | tail -1 | cut -f1)" >> $result-size
}

bench () {
	$sleep
	echo "$@" >> $log
	eval /usr/bin/time -o $tmp -f \'bt=\"$timefmt\"\' "$@" >> $log 2>&1
        sed -i 's/Command.*//' $tmp
        source $tmp
	echo " $bt"
        benchtime="`echo "scale=5; $benchtime + $bt" | bc`"
}

buildit() {
	flagname=$1; shift
	make clean >> $log 2>&1
	bench make -j$j CC=$CC CXX=$CXX $flagname='"$CFLAGS"' "$@"
}

build_make() {
	build_native buildit "$@"
}

build_native() {
        tmp="`mktemp`"
        benchtime="0.0" benchi="0"

	echo -n "  Building ..."
	"$@"; : $(( benchi++ ))
	echo -n "  Building ..."
	"$@"; : $(( benchi++ ))
#	echo -n "  Building ..."
#	"$@"; : $(( benchi++ ))

        benchtime="`echo "scale=5; $benchtime / $benchi" | bc`"

        echo "Avg: $benchtime"
        echo "$benchtime" >> $result-bt
        rm $tmp
}

build_configure() {
	CFLAGS=${CFLAGS/-fprofile*/} CXXFLAGS=${CXXFLAGS/-fprofile*/} \
		./configure --prefix="$prefix" "$@" >> $log 2>&1
}

benchit() {
	tmp="`mktemp`"
        bench_native bench "$@"
	rm -f $tmp
}

bench_make() {
	benchit make -j$j "$@"
}

bench_run() {
	$sleep
	benchit "$@"
}

bench_native() {
	# warm up caches
	benchtime="0.0"
	#echo -n "  Running (cache warmup) ..."; "$@"
	benchtime="0.0" benchi=0
	echo -n "  Running ..."
	"$@"; : $(( benchi++ ))
	echo -n "  Running ..."
	"$@"; : $(( benchi++ ))
#	echo -n "  Running ..."
#	"$@"; : $(( benchi++ ))

	benchtime="`echo "scale=5; $benchtime / $benchi" | bc`"

	echo "Avg: $benchtime"
	echo "$benchtime" >> $result-rt
}

prepare_tar() {
	echo "  Preparing tar files"
	[ -f data.tar ] || bunzip2 -c $DOWNLOADDIR/gcc-4.5.1.tar.bz2 |
		dd bs=1024 count=65636 > data.tar

	[ -f data.bin ] ||
		curl http://dl.t2-project.org/binary/unstable/8.0-trunk/t-resc-0.7/t-resc-0.7.1-x86-i486.iso |
		dd bs=1024 count=64k > data.bin
}

prepare_gzip() {
	prepare_tar
	echo "  Preparing gzip files"
	[ -f data.tar.gz ] || gzip -9 -c data.tar > data.tar.gz
	[ -f data.bin.gz ] || gzip -9 -c data.bin > data.bin.gz
}

prepare_bzip2() {
	prepare_tar
	echo "  Preparing bzip2 files"
	[ -f data.tar.bz2 ] || bzip2 -9 -c data.tar > data.tar.bz2
	[ -f data.bin.bz2 ] || bzip2 -9 -c data.bin > data.bin.bz2
}

prepare_zstd() {
	prepare_tar
	echo "  Preparing zstd files"
	[ -f data.tar.zst ] || zstd -16 < data.tar > data.tar.zst
	[ -f data.bin.zst ] || zstd -16 < data.bin > data.bin.zst
}


prepare_mp3() {
	echo "  Preparing mp3 files"
	[ -f data.mp3 ] || curl -o data.mp3 http://dl.exactcode.de/getready.mp3
	[ -f song34.mp3 ] || curl -o song34.mp3 https://ftp.openbsd.org/pub/OpenBSD/songs/song34.mp3
	[ -f song35.mp3 ] || curl -o song35.mp3 https://ftp.openbsd.org/pub/OpenBSD/songs/song35.mp3
}

prepare_zstd() {
       	prepare_tar
       	echo "  Preparing zstd files"
        [ -f data.tar.zst ] || zstd -16 < data.tar > data.tar.zst
       	[ -f data.bin.zst ] || zstd -16 < data.bin > data.bin.zst
}

prepare_wav() {
	prepare_mp3
	echo "  Preparing wav files"
	[ -f data.wav ] || madplay data.mp3 -o data.wav
	[ -f song34.wav ] || madplay song34.mp3 -o song34.wav
	[ -f song35.wav ] || madplay song35.mp3 -o song35.wav
}

prepare_jpg() {
	echo "  Preparing jpg files"
	[ -f zetaoph.jpg ] || curl -O https://www.nasa.gov/sites/default/files/thumbnails/image/zetaoph.jpg
	[ -f iss024e014263~orig.jpg ] || curl -O https://images-assets.nasa.gov/image/iss024e014263/iss024e014263~orig.jpg
	[ -f iss060e033385.jpg ] || curl -O https://www.nasa.gov/sites/default/files/thumbnails/image/iss060e033385.jpg
	[ -f Moonrise.jpg ] || curl -O https://www.esa.int/var/esa/storage/images/esa_multimedia/images/2022/06/moonrise/24095114-1-eng-GB/Moonrise.jpg
}

perror() {
	echo "ERROR while preparing the data"
	# cleanup empty data files
	find . -maxdepth 1 -size 0 \( -name 'data.*' -o -name 'song*' \) -delete
	exit 1
}

mkdir -p logs
mkdir -p results

CC=${CC:-gcc}
CXX=${CXX:-g++}
CFLAGS="${CFLAGS:--O2} -s" # always strip by default
CXXFLAGS="${CXXFLAGS:--O2} -s"
LDFLAGS="-lgcov"

echo
echo "=> Run name: $name (-j$j)"
echo "   CC  used: $CC (`$CC -dumpversion`) $CFLAGS"
echo "   CXX used: $CXX (`$CXX -dumpversion`) $CXXFLAGS"

profile() {
	local pkg="$1"
	case $pkg in
		openssl*)
			# bench_make test
			bench_openssl() {
			bt=`(./apps/openssl speed rsa512 dsa512 -mr 2>&1 | egrep '^\+F' | \
			     cut -d : -f 4-5 | sed 's/:/\n/g' |  sed 's,$, * 1000 + \\\,'; echo 0) | \
			     bc`
			echo "  $bt"
			benchtime="`echo "scale=5; $benchtime + $bt" | bc`"
			}

			bench_native bench_openssl
			;;
		gnupg*)
			bench_make check
			;;
		gzip*)
			DATADIR=$DATADIR bench_run ../bench_gzip
			;;
		zstd*)
			DATADIR=$DATADIR bench_run ../bench_zstd
			;;
		bzip2*)
			DATADIR=$DATADIR bench_run ../bench_bzip2
			;;
		libmad*)
			bench_run $prefix/bin/madplay -o null: \
			          $DATADIR/data.mp3{,} $DATADIR/song35.mp3{,} \
			          $DATADIR/song34.mp3{,}
			;;
		Botan*)
			make CXX=$CXX CHECK_OPT="$CFLAGS" MACH_OPT="" check >> $log 2>&1

			bench_botan() {
			bt="`(echo -n "scale=5; 1000 / "
			      ./check --benchmark --seconds=2 | grep "Overall speed" |
			      sed 's/Overall speed average: //'
			     ) | bc`"
			echo " $bt"
			benchtime="`echo "scale=5; $benchtime + $bt" | bc`"
			}

			bench_native bench_botan
			;;
		tramp3d*)
			bench_run $prefix/bin/tramp3d -n 3
			;;
		lame*)
			benchtime="0.0"
			bench ./frontend/lame --silent --preset 128 $DATADIR/song34.wav /dev/null
			bench ./frontend/lame --silent --preset 128 $DATADIR/song35.wav /dev/null
			bench ./frontend/lame --silent --preset 128 $DATADIR/data.wav /dev/null
			echo "$benchtime" >> $result-rt
			;;
		jpeg*)
			benchtime="0.0"
			bench ./djpeg $DATADIR/zetaoph.jpg \> x
			bench ./cjpeg x \> /dev/null
			bench ./djpeg $DATADIR/iss060e033385.jpg \> x
			bench ./cjpeg x \> /dev/null
			bench ./djpeg $DATADIR/Moonrise.jpg \> x
			bench ./cjpeg x \> /dev/null
			bench ./djpeg $DATADIR/iss024e014263~orig.jpg \> x
			bench ./cjpeg x \> /dev/null
			echo "$benchtime" >> $result-rt
			;;
		lua*)
			bench_run ./lua ../test/life.lua \> /dev/null
			;;
		*) # e.g. linux
			echo "No runtime benchmark."
			;;
	esac
}

for pkg in $*; do
	pkg=${pkg%/*}
	echo $pkg
	log="$PWD/logs/${pkg}_$name-log"
	result="$PWD/results/${pkg}_$name"

	# truncate log
	echo -n "" > $log

	prefix="$PWD/bin-$name"
	export PATH="$prefix/bin:$PATH"

	var_insert LD_LIBRARY_PATH ":" "$prefix/lib"
        var_insert LD_LIBRARY_PATH ":" .

	export LD_LIBRARY_PATH

	trap perror ERR
	set -E
	pushd $DATADIR > /dev/null
	case $pkg in
		bzip2*)
			prepare_bzip2
			;;
		libmad*)
			prepare_mp3
			;;
		jpeg*)
			prepare_jpg
			;;
		lame*)
			prepare_wav
			;;
		gzip*)
			prepare_gzip
			;;
		zstd*)
			prepare_zstd
			;;
	esac
	popd > /dev/null
	set +E
	trap error ERR

	if [ -d $pkg ]; then
		pushd $pkg > /dev/null
	elif [ -f $pkg.cpp ]; then
		pushd . > /dev/null
	else
		echo "\"$pkg\" is not a supported app, skipping"
		continue
	fi
	case $pkg in
		bzip2*)
			build_make CFLAGS
			size bzip2
			;;
		openssl*)
			./config no-asm no-shared >> $log
			build_make CFLAG
			size apps/openssl
			;;
		jpeg*)
			build_configure
			build_make CFLAGS
			size cjpeg djpeg $(readlink -f .lib/libjpeg.so)
			;;
		libmad*)
			build_configure
			build_make CFLAGS
			make install >> $log
			cd ../madplay-*
			build_configure --disable-fpm CPPFLAGS="-I$prefix/include" LDFLAGS="$LDFLAGS -L$prefix/lib"
			make clean >> $log 2>&1
			make CC=$CC CFLAGS="$CFLAGS" >> $log 2>&1
			make install >> $log 2>&1
			size $prefix/bin/madplay $prefix/lib/$(readlink -f libmad.so)
			;;
		Botan*)
			./configure.py --disable-asm >> $log 2>&1
			build_make LIB_OPT MACH_OPT='""'
			make CXX=$CXX CHECK_OPT="$CFLAGS" MACH_OPT="" >> $log 2>&1
			size check $(readlink -f libbotan.so)
			;;
		tramp3d*)
			mkdir -p $prefix/bin/
			build_native bench $CXX $CXXFLAGS \
			             -o $prefix/bin/tramp3d \
			             $pkg.cpp
			size $prefix/bin/tramp3d
			;;
		gnupg*)
			CFLAGS="$CFLAGS -fcommon"
			build_configure --disable-asm
			build_make CFLAGS
			size g10/gpg
			;;
		lame*)
			build_configure --disable-nasm --disable-gtktest
			echo "#undef HAVE_XMMINTRIN_H" >> config.h
			build_make CFLAGS
			size frontend/lame
			;;
		gzip*)
			build_configure
			build_make CFLAGS
			size gzip
			;;
               	zstd*)
			CFLAGS="$CFLAGS -fPIC"
			build_make CFLAGS HAVE_HASH=0 ZSTD_LEGACY_SUPPORT=0 # CXXFLAGS? # disable XZ support
			size $(readlink -f zstd) $(readlink -f lib/libzstd.so)
			;;
		lua*)
			cd src
			build_make CFLAGS generic MYLIBS="$LDFLAGS"
			size lua
			;;
		*)
			echo "\"$pkg\" is not a supported app, skipping"
			continue
			;;
	esac

	profile $pkg

	popd > /dev/null
done
