mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-28 16:36:14 +01:00
4d5047e0e7
The main use of the performance test is to run it for two (or more) commits and compare the results. Doing that manually, is cumbersome. Add a (very hacky) script to help with that. For usage, see the comment on top of the script. Example: # first: meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true # then: GLIB_PERFORMANCE_FACTOR=17.06 \ PERF='perf stat -r 4 -B' \ PATCH="2.80.0..th/performance" \ COMMITS="2.79.3 2.80.0" \ /tmp/performance-run.sh -s 1 property-get property-set This will build the requested $COMMITS and print something like: ... >>> combined result > /tmp/glib-performance-output.all Running test property-get property-get: Property get per second: 35742719 37208288 (+4.1%) Running test property-set property-set: Property set per second: 32341232 36942399 (+14.2%) Running test property-get property-get: Property get per second: 36934401 37143479 (+0.566%) Running test property-set property-set: Property set per second: 38046387 38165548 (+0.313%) Running test property-get property-get: Property get per second: 34759576 36359761 (+4.6%) Running test property-set property-set: Property set per second: 35262505 37651733 (+6.78%) Running test property-get property-get: Property get per second: 37014537 32870906 (-11.2%) Running test property-set property-set: Property set per second: 36633026 38216846 (+4.32%) Performance counter stats for './build/gobject/tests/performance/performance -s 1 property-get property-set' (4 runs): 1,312.18 msec task-clock:u # 1.000 CPUs utilized ( +- 4.82% ) 0 context-switches:u # 0.000 /sec 0 cpu-migrations:u # 0.000 /sec 121 page-faults:u # 92.213 /sec ( +- 0.24% ) 5,221,701,009 cycles:u # 3.979 GHz ( +- 2.61% ) 19,035,814,175 instructions:u # 3.65 insn per cycle ( +- 0.00% ) 4,335,306,010 branches:u # 3.304 G/sec ( +- 0.00% ) 13,031 branch-misses:u # 0.00% of all branches ( +- 4.17% ) TopdownL1 # 10.3 % tma_backend_bound # 5.3 % tma_bad_speculation # 11.4 % tma_frontend_bound # 73.1 % tma_retiring ( +- 2.15% ) [1] 1.3127 +- 0.0634 seconds time elapsed ( +- 4.83% ) [2] 1.2631 +- 0.0253 seconds time elapsed ( +- 2.00% ) property-get: Property get per second: 35742719 , 36934401 , 34759576 , 37014537 ; 37208288 , 37143479 , 36359761 , 32870906 ; property-set: Property set per second: 32341232 , 38046387 , 35262505 , 36633026 ; 36942399 , 38165548 , 37651733 , 38216846 ;
225 lines
7.8 KiB
Bash
Executable File
225 lines
7.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright (C) 2024 Red Hat, Inc.
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
# Run ./build/gobject/tests/performance/performance for several commits
|
|
# and compare the result.
|
|
#
|
|
# Howto:
|
|
#
|
|
# 1) configure the build. For example run
|
|
# $ git clean -fdx
|
|
# $ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true
|
|
# Beware, that running the script will check out other commits,
|
|
# build the tree and run `ninja install`. Don't have important
|
|
# work there.
|
|
#
|
|
# 2) run the script. Set $COMMITS to the list of commit sha's to test.
|
|
# Environment variables:
|
|
# COMMITS: list of git references to test.
|
|
# PATCH: if set, after checking out each commit, run `git cherry-pick $PATCH`
|
|
# before building.
|
|
# PREPARE_CMD: if set, invoke $PREPARE_CMD after checking out commit. Can be used
|
|
# to patch the sources.
|
|
# PERF: if set, run performance test via perf. Set for example, `PERF="perf stat -r 10 -B"`
|
|
# When setting `PERF`, you probably also want to set GLIB_PERFORMANCE_FACTOR,
|
|
# which depends on the test (run the test in verbose mode to find a suitable factor).
|
|
# STRIP: if set to 1, call `strip` on the library and binary before running.
|
|
# Arguments: arguments are directly passed to performance. For example try "-s 1".
|
|
#
|
|
# Example:
|
|
#
|
|
# # once:
|
|
# git clean -fdx
|
|
# meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true
|
|
#
|
|
# # test:
|
|
# COMMIT_END=my-test-branch
|
|
# COMMIT_START="$(git merge-base origin/main "$COMMIT_END")"
|
|
# PERF="" PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -s 5
|
|
# PERF="" PATCH="" COMMITS=" $COMMIT_START $( git log --reverse --pretty=%H "$COMMIT_START..$COMMIT_END" ) " /tmp/performance-run.sh -s 5
|
|
#
|
|
# GLIB_PERFORMANCE_FACTOR=17.06 PERF='perf stat -r 3 -B' PATCH="" COMMITS=" $COMMIT_START $COMMIT_END " /tmp/performance-run.sh -s 1 property-get
|
|
|
|
set -e
|
|
|
|
usage() {
|
|
sed -n '4,/^$/ s/^#\( \(.*\)\|\)$/\2/p' "$0"
|
|
}
|
|
|
|
if [ "$#" -eq 1 ] && [ "$1" == "-h" ] ; then
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
die() {
|
|
printf "%s\n" "$*"
|
|
exit 1
|
|
}
|
|
|
|
die_with_last_cmd() {
|
|
cat /tmp/glib-performance-last-cmd || :
|
|
die "$@"
|
|
}
|
|
|
|
read -ra COMMITS_V -d '' <<<"$COMMITS" || :
|
|
|
|
[ "${#COMMITS_V[@]}" -gt 0 ] || die "Must set \$COMMITS"
|
|
|
|
COMMITS_SHA=()
|
|
for commit in "${COMMITS_V[@]}" ; do
|
|
c="$(git rev-parse --verify "$commit^{commit}")" || die "invalid git reference \"$commit\""
|
|
COMMITS_SHA+=( "$c" )
|
|
done
|
|
|
|
_list_commits() {
|
|
local PREFIX="$1"
|
|
local idx
|
|
local I
|
|
|
|
I=0
|
|
for idx in "${!COMMITS_V[@]}" ; do
|
|
I=$((I+1))
|
|
echo "${PREFIX}[$I] $(git log -n1 --oneline "${COMMITS_SHA[$idx]}") (${COMMITS_V[$idx]})"
|
|
done
|
|
}
|
|
|
|
cat << EOF
|
|
|
|
Testing commits:
|
|
|
|
$(_list_commits " ")
|
|
|
|
\$ meson build -Dprefix=/tmp/glib/ -Db_lto=true --buildtype release -Ddebug=true
|
|
\$ PATCH=$(printf '%q' "$PATCH") \\
|
|
PREPARE_CMD=$(printf '%q' "$PREPARE_CMD") \\
|
|
PERF=$(printf '%q' "$PERF") \\
|
|
GLIB_PERFORMANCE_FACTOR=$(printf '%q' "$GLIB_PERFORMANCE_FACTOR") \\
|
|
STRIP=$(printf '%q' "$STRIP") \\
|
|
COMMITS=$(printf '%q' "$COMMITS") \\
|
|
$0$(printf ' %q' "$@")
|
|
|
|
EOF
|
|
|
|
_get_timing() {
|
|
local LINE_NUM="$1"
|
|
local LINE_PREFIX="$2"
|
|
local FILE="$3"
|
|
|
|
sed -n "$LINE_NUM s/^$LINE_PREFIX: //p" "$FILE"
|
|
}
|
|
|
|
_perc() {
|
|
awk -v n1="$1" -v n2="$2" 'BEGIN { printf("%+0.3g%\n", (n2 - n1) / n1 * 100.0); }'
|
|
}
|
|
|
|
_cmd() {
|
|
# printf ' $' ; printf ' %s' "$@" ; printf '\n'
|
|
"$@"
|
|
}
|
|
|
|
|
|
I=0
|
|
for idx in "${!COMMITS_V[@]}" ; do
|
|
commit="${COMMITS_V[$idx]}"
|
|
commit_sha="${COMMITS_SHA[$idx]}"
|
|
I=$((I+1))
|
|
echo -n ">>> [$I] test [ $(git log -n1 --oneline "$commit") ]"
|
|
git checkout -f "$commit_sha" &> /tmp/glib-performance-last-cmd || (echo ...; die_with_last_cmd "Failure to checkout \"$commit\"")
|
|
touch glib/gdataset.c gobject/gobject.c gobject/tests/performance/performance.c
|
|
if [ "$PATCH" != "" ] ; then
|
|
read -ra PATCH_ARR -d '' <<<"$PATCH" || :
|
|
for p in "${PATCH_ARR[@]}" ; do
|
|
git cherry-pick "$p" &> /tmp/glib-performance-last-cmd || (echo ...; die_with_last_cmd "Failure to cherry-pick \"$PATCH\"")
|
|
done
|
|
fi
|
|
if [ "$PREPARE_CMD" != "" ] ; then
|
|
I="$I" COMMIT="$commit" "$PREPARE_CMD" &> /tmp/glib-performance-last-cmd || (echo ...; die_with_last_cmd "\$PREPARE_CMD failed")
|
|
fi
|
|
echo " commit $(git rev-parse --verify HEAD) > /tmp/glib-performance-output.$I"
|
|
( ninja -C build || ninja -C build ) &> /tmp/glib-performance-last-cmd || die_with_last_cmd "Failure to build with \`ninja -C build\`"
|
|
ninja -C build install &> /tmp/glib-performance-last-cmd || die_with_last_cmd "FAilure to install with \`ninja -C build install\`"
|
|
if [ "$STRIP" = 1 ] ; then
|
|
strip ./build/gobject/libgobject-2.0.so ./build/glib/libglib-2.0.so.0 ./build/gobject/tests/performance/performance
|
|
fi
|
|
|
|
# ls -lad -L \
|
|
# ./build/gobject/libgobject-2.0.so \
|
|
# ./build/glib/libglib-2.0.so \
|
|
# ./build/gobject/tests/performance/performance
|
|
# ldd ./build/gobject/tests/performance/performance
|
|
|
|
(
|
|
if [ -z "$PERF" ] ; then
|
|
TESTRUN="$I" TESTCOMMIT="$commit" ./build/gobject/tests/performance/performance "$@"
|
|
else
|
|
TESTRUN="$I" TESTCOMMIT="$commit" $PERF ./build/gobject/tests/performance/performance "$@"
|
|
fi
|
|
) |& tee "/tmp/glib-performance-output.$I" || :
|
|
[ "${PIPESTATUS[0]}" -eq 0 ] || die "Performance test failed"
|
|
done
|
|
|
|
merge_output() {
|
|
(
|
|
declare -A RES
|
|
LINE_NUM=0
|
|
OLD_IFS="$IFS"
|
|
while IFS=$'\n' read -r LINE ; do
|
|
LINE="${LINE:1}"
|
|
LINE_NUM=$((LINE_NUM+1))
|
|
line_regex='^([a-zA-Z0-9].*): +([0-9.]+)$'
|
|
|
|
if [[ "$LINE" =~ $line_regex ]] ; then
|
|
LINE_PREFIX="${BASH_REMATCH[1]}"
|
|
T1="${BASH_REMATCH[2]}"
|
|
echo -n "$LINE_PREFIX: $T1"
|
|
RES["$LINE_PREFIX"]="${RES[$LINE_PREFIX]} $T1"
|
|
for J in $(seq 2 "${#COMMITS_V[@]}") ; do
|
|
T="$(_get_timing "$LINE_NUM" "$LINE_PREFIX" "/tmp/glib-performance-output.$J")"
|
|
echo -n " $T ($(_perc "$T1" "$T"))"
|
|
RES["$LINE_PREFIX"]="${RES[$LINE_PREFIX]} $T"
|
|
done
|
|
echo
|
|
continue
|
|
fi
|
|
if [ -n "$PERF" ] ; then
|
|
if [[ "$LINE" == *"seconds time elapsed"* ]] ; then
|
|
echo "[1] $LINE"
|
|
for J in $(seq 2 "${#COMMITS_V[@]}") ; do
|
|
echo "[$J] $(sed -n "$LINE_NUM s/seconds time elapsed/\\0/p" "/tmp/glib-performance-output.$J")"
|
|
done
|
|
continue
|
|
fi
|
|
fi
|
|
echo "$LINE"
|
|
done < <( sed 's/^/x/' "/tmp/glib-performance-output.1" )
|
|
|
|
IFS="$OLD_IFS"
|
|
if [ -n "$PERF" ] ; then
|
|
for LINE_PREFIX in "${!RES[@]}"; do
|
|
# The values are interleaved. To cumbersome to process in bash.
|
|
read -ra T -d '' <<<"${RES[$LINE_PREFIX]}" || :
|
|
read -ra T_SORTED -d '' < <(printf '%s\n' "${T[@]}" | awk -v C="${#COMMITS_V[@]}" '{ print (1 + (NR-1) % C) " " $0 }' | sort -n -s | sed 's/^[0-9]\+ *//' ) || :
|
|
NGROUP="$(( "${#T_SORTED[@]}" / "${#COMMITS_V[@]}" ))"
|
|
echo -n "$LINE_PREFIX: "
|
|
SEP=''
|
|
for J in $(seq 0 "${#T_SORTED[@]}") ; do
|
|
echo -n "$SEP${T_SORTED[$J]}"
|
|
if [ $(( (J+1) % NGROUP )) = 0 ]; then
|
|
echo -n " ; "
|
|
SEP=''
|
|
else
|
|
SEP=" , "
|
|
fi
|
|
done
|
|
echo
|
|
done
|
|
fi
|
|
) | tee "/tmp/glib-performance-output.all"
|
|
}
|
|
|
|
echo ">>> combined result > /tmp/glib-performance-output.all"
|
|
merge_output
|