]> git.proxmox.com Git - libgit2.git/blame - tests/benchmarks/benchmark.sh
Merge https://salsa.debian.org/debian/libgit2 into proxmox/bullseye
[libgit2.git] / tests / benchmarks / benchmark.sh
CommitLineData
ad5611d8
TR
1#!/bin/bash
2
3set -eo pipefail
4
5#
6# parse the command line
7#
8
9usage() { echo "usage: $(basename "$0") [--cli <path>] [--baseline-cli <path>] [--suite <suite>] [--json <path>] [--zip <path>] [--verbose] [--debug]"; }
10
11TEST_CLI="git"
12BASELINE_CLI=
13SUITE=
14JSON_RESULT=
15ZIP_RESULT=
16OUTPUT_DIR=
17VERBOSE=
18DEBUG=
19NEXT=
20
21for a in "$@"; do
22 if [ "${NEXT}" = "cli" ]; then
23 TEST_CLI="${a}"
24 NEXT=
25 elif [ "${NEXT}" = "baseline-cli" ]; then
26 BASELINE_CLI="${a}"
27 NEXT=
28 elif [ "${NEXT}" = "suite" ]; then
29 SUITE="${a}"
30 NEXT=
31 elif [ "${NEXT}" = "json" ]; then
32 JSON_RESULT="${a}"
33 NEXT=
34 elif [ "${NEXT}" = "zip" ]; then
35 ZIP_RESULT="${a}"
36 NEXT=
37 elif [ "${NEXT}" = "output-dir" ]; then
38 OUTPUT_DIR="${a}"
39 NEXT=
40 elif [ "${a}" = "c" ] || [ "${a}" = "--cli" ]; then
41 NEXT="cli"
42 elif [[ "${a}" == "-c"* ]]; then
43 TEST_CLI="${a/-c/}"
44 elif [ "${a}" = "b" ] || [ "${a}" = "--baseline-cli" ]; then
45 NEXT="baseline-cli"
46 elif [[ "${a}" == "-b"* ]]; then
47 BASELINE_CLI="${a/-b/}"
48 elif [ "${a}" = "-s" ] || [ "${a}" = "--suite" ]; then
49 NEXT="suite"
50 elif [[ "${a}" == "-s"* ]]; then
51 SUITE="${a/-s/}"
52 elif [ "${a}" = "-v" ] || [ "${a}" == "--verbose" ]; then
53 VERBOSE=1
54 elif [ "${a}" == "--debug" ]; then
55 VERBOSE=1
56 DEBUG=1
57 elif [ "${a}" = "-j" ] || [ "${a}" == "--json" ]; then
58 NEXT="json"
59 elif [[ "${a}" == "-j"* ]]; then
60 JSON_RESULT="${a/-j/}"
61 elif [ "${a}" = "-z" ] || [ "${a}" == "--zip" ]; then
62 NEXT="zip"
63 elif [[ "${a}" == "-z"* ]]; then
64 ZIP_RESULT="${a/-z/}"
65 elif [ "${a}" = "--output-dir" ]; then
66 NEXT="output-dir"
67 else
68 echo "$(basename "$0"): unknown option: ${a}" 1>&2
69 usage 1>&2
70 exit 1
71 fi
72done
73
74if [ "${NEXT}" != "" ]; then
75 usage 1>&2
76 exit 1
77fi
78
79if [ "${OUTPUT_DIR}" = "" ]; then
80 OUTPUT_DIR=${OUTPUT_DIR:="$(mktemp -d)"}
81 CLEANUP_DIR=1
82fi
83
84#
85# collect some information about the test environment
86#
87
88SYSTEM_OS=$(uname -s)
89if [ "${SYSTEM_OS}" = "Darwin" ]; then SYSTEM_OS="macOS"; fi
90
91SYSTEM_KERNEL=$(uname -v)
92
93fullpath() {
94 if [[ "$(uname -s)" == "MINGW"* && $(cygpath -u "${TEST_CLI}") == "/"* ]]; then
95 echo "${TEST_CLI}"
96 elif [[ "${TEST_CLI}" == "/"* ]]; then
97 echo "${TEST_CLI}"
98 else
99 which "${TEST_CLI}"
100 fi
101}
102
103cli_version() {
104 if [[ "$(uname -s)" == "MINGW"* ]]; then
105 $(cygpath -u "$1") --version
106 else
107 "$1" --version
108 fi
109}
110
111TEST_CLI_NAME=$(basename "${TEST_CLI}")
112TEST_CLI_PATH=$(fullpath "${TEST_CLI}")
113TEST_CLI_VERSION=$(cli_version "${TEST_CLI}")
114
115if [ "${BASELINE_CLI}" != "" ]; then
116 if [[ "${BASELINE_CLI}" == "/"* ]]; then
117 BASELINE_CLI_PATH="${BASELINE_CLI}"
118 else
119 BASELINE_CLI_PATH=$(which "${BASELINE_CLI}")
120 fi
121
122 BASELINE_CLI_NAME=$(basename "${BASELINE_CLI}")
123 BASELINE_CLI_PATH=$(fullpath "${BASELINE_CLI}")
124 BASELINE_CLI_VERSION=$(cli_version "${BASELINE_CLI}")
125fi
126
127#
128# run the benchmarks
129#
130
131echo "##############################################################################"
132if [ "${SUITE}" != "" ]; then
133 SUITE_PREFIX="${SUITE/::/__}"
134 echo "## Running ${SUITE} benchmarks"
135else
136 echo "## Running all benchmarks"
137fi
138echo "##############################################################################"
139echo ""
140
141if [ "${BASELINE_CLI}" != "" ]; then
142 echo "# Baseline CLI: ${BASELINE_CLI} (${BASELINE_CLI_VERSION})"
143fi
144echo "# Test CLI: ${TEST_CLI} (${TEST_CLI_VERSION})"
145echo ""
146
147BENCHMARK_DIR=${BENCHMARK_DIR:=$(dirname "$0")}
148ANY_FOUND=
149ANY_FAILED=
150
151indent() { sed "s/^/ /"; }
152time_in_ms() { if [ "$(uname -s)" = "Darwin" ]; then date "+%s000"; else date "+%s%N" ; fi; }
153humanize_secs() {
154 units=('s' 'ms' 'us' 'ns')
155 unit=0
156 time="${1}"
157
158 if [ "${time}" = "" ]; then
159 echo ""
160 return
161 fi
162
163 # bash doesn't do floating point arithmetic. ick.
164 while [[ "${time}" == "0."* ]] && [ "$((unit+1))" != "${#units[*]}" ]; do
165 time="$(echo | awk "{ print ${time} * 1000 }")"
166 unit=$((unit+1))
167 done
168
169 echo "${time} ${units[$unit]}"
170}
171
172TIME_START=$(time_in_ms)
173
174for TEST_PATH in "${BENCHMARK_DIR}"/*; do
175 TEST_FILE=$(basename "${TEST_PATH}")
176
177 if [ ! -f "${TEST_PATH}" ] || [ ! -x "${TEST_PATH}" ]; then
178 continue
179 fi
180
181 if [[ "${TEST_FILE}" != *"__"* ]]; then
182 continue
183 fi
184
185 if [[ "${TEST_FILE}" != "${SUITE_PREFIX}"* ]]; then
186 continue
187 fi
188
189 ANY_FOUND=1
190 TEST_NAME="${TEST_FILE/__/::}"
191
192 echo -n "${TEST_NAME}:"
193 if [ "${VERBOSE}" = "1" ]; then
194 echo ""
195 else
196 echo -n " "
197 fi
198
199 if [ "${DEBUG}" = "1" ]; then
200 SHOW_OUTPUT="--show-output"
201 fi
202
203 OUTPUT_FILE="${OUTPUT_DIR}/${TEST_FILE}.out"
204 JSON_FILE="${OUTPUT_DIR}/${TEST_FILE}.json"
205 ERROR_FILE="${OUTPUT_DIR}/${TEST_FILE}.err"
206
207 FAILED=
208 ${TEST_PATH} --cli "${TEST_CLI}" --baseline-cli "${BASELINE_CLI}" --json "${JSON_FILE}" ${SHOW_OUTPUT} >"${OUTPUT_FILE}" 2>"${ERROR_FILE}" || FAILED=1
209
210 if [ "${FAILED}" = "1" ]; then
211 if [ "${VERBOSE}" != "1" ]; then
212 echo "failed!"
213 fi
214
215 indent < "${ERROR_FILE}"
216 ANY_FAILED=1
217 continue
218 fi
219
220 # in verbose mode, just print the hyperfine results; otherwise,
221 # pull the useful information out of its json and summarize it
222 if [ "${VERBOSE}" = "1" ]; then
223 indent < "${OUTPUT_FILE}"
224 else
225 jq -r '[ .results[0].mean, .results[0].stddev, .results[1].mean, .results[1].stddev ] | @tsv' < "${JSON_FILE}" | while IFS=$'\t' read -r one_mean one_stddev two_mean two_stddev; do
226 one_mean=$(humanize_secs "${one_mean}")
227 one_stddev=$(humanize_secs "${one_stddev}")
228
229 if [ "${two_mean}" != "" ]; then
230 two_mean=$(humanize_secs "${two_mean}")
231 two_stddev=$(humanize_secs "${two_stddev}")
232
233 echo "${one_mean} ± ${one_stddev} vs ${two_mean} ± ${two_stddev}"
234 else
235 echo "${one_mean} ± ${one_stddev}"
236 fi
237 done
238 fi
239
240 # add our metadata to the hyperfine json result
241 jq ". |= { \"name\": \"${TEST_NAME}\" } + ." < "${JSON_FILE}" > "${JSON_FILE}.new" && mv "${JSON_FILE}.new" "${JSON_FILE}"
242done
243
244TIME_END=$(time_in_ms)
245
246if [ "$ANY_FOUND" != "1" ]; then
247 echo ""
248 echo "error: no benchmark suite \"${SUITE}\"."
249 echo ""
250 exit 1
251fi
252
253escape() {
254 echo "${1//\\/\\\\}"
255}
256
257# combine all the individual benchmark results into a single json file
258if [ "${JSON_RESULT}" != "" ]; then
259 if [ "${VERBOSE}" = "1" ]; then
260 echo ""
261 echo "# Writing JSON results: ${JSON_RESULT}"
262 fi
263
264 SYSTEM_JSON="{ \"os\": \"${SYSTEM_OS}\", \"kernel\": \"${SYSTEM_KERNEL}\" }"
265 TIME_JSON="{ \"start\": ${TIME_START}, \"end\": ${TIME_END} }"
266 TEST_CLI_JSON="{ \"name\": \"${TEST_CLI_NAME}\", \"path\": \"$(escape "${TEST_CLI_PATH}")\", \"version\": \"${TEST_CLI_VERSION}\" }"
267 BASELINE_CLI_JSON="{ \"name\": \"${BASELINE_CLI_NAME}\", \"path\": \"$(escape "${BASELINE_CLI_PATH}")\", \"version\": \"${BASELINE_CLI_VERSION}\" }"
268
269 if [ "${BASELINE_CLI}" != "" ]; then
270 EXECUTOR_JSON="{ \"baseline\": ${BASELINE_CLI_JSON}, \"cli\": ${TEST_CLI_JSON} }"
271 else
272 EXECUTOR_JSON="{ \"cli\": ${TEST_CLI_JSON} }"
273 fi
274
275 # add our metadata to all the test results
276 jq -n "{ \"system\": ${SYSTEM_JSON}, \"time\": ${TIME_JSON}, \"executor\": ${EXECUTOR_JSON}, \"tests\": [inputs] }" "${OUTPUT_DIR}"/*.json > "${JSON_RESULT}"
277fi
278
279# combine all the data into a zip if requested
280if [ "${ZIP_RESULT}" != "" ]; then
281 if [ "${VERBOSE}" = "1" ]; then
282 if [ "${JSON_RESULT}" = "" ]; then echo ""; fi
283 echo "# Writing ZIP results: ${ZIP_RESULT}"
284 fi
285
286 zip -jr "${ZIP_RESULT}" "${OUTPUT_DIR}" >/dev/null
287fi
288
289if [ "$CLEANUP_DIR" = "1" ]; then
290 rm -f "${OUTPUT_DIR}"/*.out
291 rm -f "${OUTPUT_DIR}"/*.err
292 rm -f "${OUTPUT_DIR}"/*.json
293 rmdir "${OUTPUT_DIR}"
294fi
295
296if [ "$ANY_FAILED" = "1" ]; then
297 exit 1
298fi