#!/bin/bash

function compile() {
    set +ex

    local proj="${1:-linux}"
    local tdir="${2:-/tmp}"
    local file="${tdir}/${proj}-compile.sh"

    local repo
    case "${proj}" in
    git)
        repo=https://github.com/git/git.git
        ;;
    linux)
        repo=https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
        ;;
    inkscape)
        repo=https://gitlab.com/inkscape/inkscape.git
        ;;
    *)
        echo >&2 "Unsupported benchmark project ${proj}!"
        echo >&2 'Expected exactly one of: git, linux or inkscape!'
        exit 127
        ;;
    esac

    set -ex

    git clone --quiet --depth 1 --recursive "${repo}" "${tdir}/${proj}" >&2

    set +x

    cat >"${file}" <<EOF
#!/bin/bash

exec 1>>'${SYD_BENCH_LOG}' 2>>'${SYD_BENCH_LOG}'
perl -pe 's/\\0/ /g; s/^/-- /; s/ +$/\\n/' < /proc/\${PPID}/cmdline

set -ex

# Ensure we don't trigger TPE.
umask 077

cd "${tdir}/${proj}"

case '${proj}' in
linux)
    make defconfig
    ;;
inkscape)
    CMAKE=(
-DBUILD_SHARED_LIBS:BOOL=TRUE
-DPACKAGE_LOCALE_DIR:PATH=/usr/share/locale
-DENABLE_BINRELOC:BOOL=FALSE
-DINKSCAPE_DATADIR:PATH=/usr/share
-DINKSCAPE_SHARE_INSTALL:PATH=/usr/share
-DLPE_ENABLE_TEST_EFFECTS:BOOL=FALSE
-DSHARE_INSTALL:PATH=/usr/share
-DWITH_ASAN:BOOL=FALSE
-DWITH_GNU_READLINE:BOOL=TRUE
-DWITH_GSOURCEVIEW:BOOL=FALSE
-DWITH_GSPELL:BOOL=TRUE
-DWITH_INTERNAL_2GEOM:BOOL=FALSE
-DWITH_INTERNAL_CAIRO:BOOL=FALSE
-DWITH_JEMALLOC:BOOL=FALSE
-DWITH_LPETOOL:BOOL=FALSE
-DWITH_MANPAGE_COMPRESSION:BOOL=TRUE
-DWITH_NLS:BOOL=TRUE
-DWITH_PROFILING:BOOL=FALSE
-DWITH_SVG2:BOOL=TRUE
-DWITH_X11:BOOL=TRUE
-DENABLE_POPPLER:BOOL=TRUE
-DENABLE_POPPLER_CAIRO:BOOL=TRUE
-DWITH_OPENMP:BOOL=TRUE
-DWITH_IMAGE_MAGICK:BOOL=FALSE
-DWITH_GRAPHICS_MAGICK:BOOL=TRUE
)
    cmake \${CMAKE[@]} .
    ;;
*)
    test -x ./configure || autoreconf -fiv
    ./configure
    ;;
esac

make -j$(nproc)

make clean
EOF

    chmod +x "${file}"

    echo -n "${file}"
}

set -ex

neofetch --stdout 2>/dev/null || uname -a
syd --version
runsc --version || echo >&2 'runsc not found!'

set +x

sudo=sudo
type -P doas &>/dev/null && sudo=doas

runsc=runsc
runsc_flags='--network=host -ignore-cgroups'
type -P runsc &>/dev/null || runsc=
if [[ -n "${runsc}" ]]; then
    if ! $sudo ${runsc} ${runsc_flags} 'do' true; then
        runsc=
        echo >&2 'runsc is broken!'
    fi
fi

# Ensure we don't trigger TPE.
umask 077

proj="${1:-linux}"
out="${PWD}"
if [[ -n "${SYD_BENCH_OUT}" ]]; then
    out="${out}/${SYD_BENCH_OUT}"
else
    out="${out}/syd-bench-${proj}-$(date -u +'%Y%m%d%H%M%S')"
fi
tmp=$(mktemp -d)

unset SYD_BENCH_KEEP_TMP
function finish() {
    if [[ -z "${SYD_BENCH_KEEP_TMP}" ]]; then
        rm -rf "${tmp}"
    else
        echo >&2 "Keeping temporary directory \`${tmp}'"
    fi
}
trap finish INT QUIT TERM EXIT

export SYD_BENCH_LOG="${out}".log
touch "${SYD_BENCH_LOG}"

script=$(compile "${proj}" "${tmp}")
test -x "$script"

argv='-pP -mallow/all+/*** -mlock:on'
p_l='-plandlock -mdefault/lock:warn -mallow/lock/all+/'
p_i='-pimmutable -mbind-tmpfs:/tmp'

box=bash
if [[ -n "${runsc}" ]]; then
    runsc_platform='systrap ptrace'
    [[ -c /dev/kvm ]] && runsc_platform+=' kvm'
    for runsc_platform in ${runsc_platform}; do
        box+=",${sudo} ${runsc} ${runsc_flags} -platform ${runsc_platform} do"
    done
fi

# "user" profile enables path hiding which is known
# to introduce considerable overhead. We disable
# it here for consistency in benchmarks. We stack
# it with the "hide" profile as an additional case
# to display the overhead of path hiding.
export SYD_USER_LPATH=off

# user profile enforces trace/force_umask:7177,
# which we relax here so we can create executables.
box+=",syd -puser -mtrace/force_umask:7077 ${argv}"
box+=",syd -puser -mtrace/force_umask:7077 ${p_l} ${argv}"
box+=",syd -puser -phide -mtrace/force_umask:7077 ${p_l} ${argv}"
box+=",syd -ppaludis ${argv}"
box+=",syd -ppaludis ${p_l} ${argv}"
box+=",syd -ppaludis -phide ${p_l} ${argv}"

opt_show_output=
if [[ -n "${SYD_BENCH_SHOW_OUTPUT}" ]]; then
    opt_show_output=--show-output
fi

export SYD_BENCH_KEEP_TMP=YesPlease
set -ex

hyperfine \
    --warmup 1 --min-runs 3 \
    ${opt_show_output} --ignore-failure --shell none \
    --export-markdown "${out}.md" \
    -L sandbox "${box}" "{sandbox} ${script}"
set +x

set +ex
unset SYD_BENCH_KEEP_TMP

mv "${out}.md" "${out}".tmp
(
    echo "# Syd benchmark: ${proj}-$(date -u +'%Y%m%d%H%M%S')"
    echo
    cat "${out}".tmp
    echo
    echo '## Machine'
    echo; echo '```'
    ( neofetch --stdout 2>/dev/null || uname -a ) |\
        sed \
            -e 's/[[:space:]]\+$//g' \
            -e '/^$/d'
    echo '```'; echo
    echo '## Syd'
    echo; echo '```'
    syd --version
    echo '```'; echo
    echo '## GVisor'
    echo; echo '```'
    runsc --version || echo 'runsc not found!'
    echo '```'
) > "${out}.md"
unlink "${out}".tmp

echo >&2 "Results were written to the file ${out}.md."
echo >&2 'Share this file and spread the fun!'

true
