Skip to content

Commit d272837

Browse files
committed
Adding Bash testing script
1 parent 5f6f49b commit d272837

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

run_tests.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/usr/bin/env bash
2+
3+
#########################################
4+
# Run benchmark scripts in succession, #
5+
# outputting results and waiting for a #
6+
# defined number of seconds in between #
7+
# successive runs to allow for CPU #
8+
# cooling and avoid thermal throttling. #
9+
#########################################
10+
# Exit status codes:
11+
# - 0 --> Success
12+
# - 1 --> GIL interpreter not found
13+
# - 2 --> Free-threaded interpreter not found
14+
# - 3 --> GIL interpreter not executable
15+
# - 4 --> Free-threaded interpreter not executable
16+
# - 5 --> Benchmark script(s) not found
17+
18+
# Exit on errors, undefined variables, or pipeline failures
19+
set -euo pipefail
20+
21+
# Path where uv installs downloaded Python interpreters
22+
PYTHON_PATH="${HOME}/.local/bin"
23+
24+
# Traditional GIL Python interpreter
25+
PYTHON_GIL="python3.14"
26+
GIL_INTERPRETER="${PYTHON_PATH}/${PYTHON_GIL}"
27+
28+
# Ensure our GIL interpreter is available & executable
29+
command -v "${GIL_INTERPRETER}" >/dev/null || { echo "Error: ${GIL_INTERPRETER} not found"; exit 1; }
30+
[ -x "${GIL_INTERPRETER}" ] || { echo "Error: ${GIL_INTERPRETER} not executable"; exit 3; }
31+
32+
# Free-threaded Python interpreter
33+
PYTHON_FT="python3.14t"
34+
FT_INTERPRETER="${PYTHON_PATH}/${PYTHON_FT}"
35+
36+
# Ensure our free-threaded interpreter is available & executable
37+
command -v "${FT_INTERPRETER}" >/dev/null || { echo "Error: ${FT_INTERPRETER} not found"; exit 2; }
38+
[ -x "${FT_INTERPRETER}" ] || { echo "Error: ${FT_INTERPRETER} not executable"; exit 4; }
39+
40+
# Number of iterations to run each script test
41+
ITERATION_COUNT=10
42+
43+
# Cooldown between successive runs to avoid CPU thermal throttling
44+
COOLDOWN_SECONDS=60
45+
46+
# Benchmark script names
47+
BASELINE_SCRIPT="mandelbrot_baseline.py"
48+
THREADING_SCRIPT="mandelbrot_threading.py"
49+
MULTIPROCESSING_SCRIPT="mandelbrot_multiprocessing.py"
50+
51+
# Ensure our scripts exist
52+
for script in "${BASELINE_SCRIPT}" "${THREADING_SCRIPT}" "${MULTIPROCESSING_SCRIPT}"; do
53+
[ -f "${script}" ] || { echo "Error: Script ${script} not found"; exit 5; }
54+
done
55+
56+
# Let's start testing!
57+
echo "===== Python 3.14 GIL vs Free-threaded Benchmark ====="
58+
echo "Date: $(date)"
59+
echo "Working directory: $(pwd)"
60+
echo "Number of CPUs: $(getconf _NPROCESSORS_ONLN 2>/dev/null || nproc 2>/dev/null || echo '?')"
61+
echo "Hostname: $(hostname)"
62+
echo "Iterations per test: ${ITERATION_COUNT}"
63+
echo "Cooldown between runs: ${COOLDOWN_SECONDS}s"
64+
echo "Python GIL version: "
65+
echo -n "-> "
66+
"${GIL_INTERPRETER}" -VV
67+
echo "Python Free-threaded version:"
68+
echo -n "-> "
69+
"${FT_INTERPRETER}" -VV
70+
echo "======================================================"
71+
echo
72+
73+
#################################
74+
# Function to run each script #
75+
# multiple times, outputting #
76+
# results. #
77+
# #
78+
# Sleep for ${COOLDOWN_SECONDS} #
79+
# between successive runs. #
80+
# #
81+
# Function arguments: #
82+
# - $1 -> interpreter to use #
83+
# - $2 -> script to run #
84+
#################################
85+
run_test() {
86+
local interpreter="${1}"
87+
local script="${2}"
88+
for run in $(seq 1 "${ITERATION_COUNT}"); do
89+
echo "Run number: ${run}"
90+
# Use Bash's built-in time utility instead of GNU time for higher precision
91+
# See: https://unix.stackexchange.com/questions/27920/why-bash-time-is-more-precise-then-gnu-time
92+
echo "Running command:"
93+
echo "-> time ${interpreter} ./${script}"
94+
echo
95+
time "${interpreter}" "./${script}"
96+
# Sleep to allow CPUs to cool and minimize thermal throttling impact
97+
echo "Cooling off for ${COOLDOWN_SECONDS} seconds..."
98+
sleep "${COOLDOWN_SECONDS}"
99+
echo
100+
echo "======================================================"
101+
done
102+
}
103+
104+
###############
105+
# GIL Testing #
106+
###############
107+
# Run traditional GIL interpreter with baseline script
108+
run_test "${GIL_INTERPRETER}" "${BASELINE_SCRIPT}"
109+
110+
# Run traditional GIL interpreter with threading script
111+
run_test "${GIL_INTERPRETER}" "${THREADING_SCRIPT}"
112+
113+
# Run traditional GIL interpreter with multiprocessing script
114+
run_test "${GIL_INTERPRETER}" "${MULTIPROCESSING_SCRIPT}"
115+
116+
117+
#########################
118+
# Free-threaded Testing #
119+
#########################
120+
# Run free-threaded interpreter with baseline script
121+
run_test "${FT_INTERPRETER}" "${BASELINE_SCRIPT}"
122+
123+
# Run free-threaded interpreter with threading script
124+
run_test "${FT_INTERPRETER}" "${THREADING_SCRIPT}"
125+
126+
# Run free-threaded interpreter with multiprocessing script
127+
run_test "${FT_INTERPRETER}" "${MULTIPROCESSING_SCRIPT}"

0 commit comments

Comments
 (0)