forked from MichaIng/DietPi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdietpi-benchmark
executable file
·365 lines (298 loc) · 12.2 KB
/
dietpi-benchmark
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
#!/bin/bash
{
#////////////////////////////////////
# DietPi Function:
# - benchmark
#
#////////////////////////////////////
# Created by Daniel Knight / [email protected] / dietpi.com
#
#////////////////////////////////////
#
# Location: /boot/dietpi/func/dietpi-benchmark
#
# Usage:
# /boot/dietpi/func/dietpi-benchmark 0 = init vars for sourcing /var/lib/dietpi/dietpi-benchmark/results
# FP_BENCHFILE=/location BENCH_FILESIZE=optional_size_MiB /boot/dietpi/func/dietpi-benchmark 1 = Benchmark $FP_BENCHFILE filesystem read/write.
# /boot/dietpi/func/dietpi-benchmark 2 = Run all benchmarks and upload to dietpi.com
# G_INTERACTIVE=0 /boot/dietpi/func/dietpi-benchmark 2 = Same as above, automated
# /boot/dietpi/func/dietpi-benchmark 3 = iPerf server
# /boot/dietpi/func/dietpi-benchmark 4 = iPerf client with prompt
#
#////////////////////////////////////
# Import DietPi-Globals --------------------------------------------------------------
. /boot/dietpi/func/dietpi-globals
readonly G_PROGRAM_NAME='DietPi-Benchmark'
G_INIT
# Import DietPi-Globals --------------------------------------------------------------
[[ $1 ]] || { G_DIETPI-NOTIFY 1 'Invalid command, please see source code'; exit 1; }
INPUT=$1
#/////////////////////////////////////////////////////////////////////////////////////
# Global
#/////////////////////////////////////////////////////////////////////////////////////
IPERF_SERVER_IP=
SHOW_RESULTS=${SHOW_RESULTS:-1} # Optional input: Show results for individual tests?
CPUBENCH_INT_MAX=${CPUBENCH_INT_MAX:-1000000} # Optional input
BENCH_FILESIZE=${BENCH_FILESIZE:-0} # Optional input for automated
[[ ${FP_BENCHFILE:=/} == '/'* ]] || { G_DIETPI-NOTIFY 1 'FP_BENCHFILE must be an absolute directory path, aborting...'; exit 1; } # Optional input
BENCH_ROOTFS_WRITE='Not tested'
BENCH_ROOTFS_READ='Not tested'
BENCH_RAM_WRITE='Not tested'
BENCH_RAM_READ='Not tested'
BENCH_CUSTOMFS_WRITE='Not tested'
BENCH_CUSTOMFS_READ='Not tested'
BENCH_CPU='Not tested'
BENCH_CPU_TEMP_START='Not tested'
BENCH_CPU_TEMP_END='Not tested'
BENCH_NET_LAN_SPEED='Not tested'
# shellcheck disable=SC1091
Load_Results(){ [[ -f '/var/lib/dietpi/dietpi-benchmark/results' ]] && . /var/lib/dietpi/dietpi-benchmark/results; }
Save_Results(){
G_EXEC mkdir -p /var/lib/dietpi/dietpi-benchmark
cat << _EOF_ > /var/lib/dietpi/dietpi-benchmark/results
BENCH_VERSION=2
BENCH_HW_MODEL=$G_HW_MODEL
BENCH_CPU='$BENCH_CPU'
BENCH_ROOTFS_WRITE='$BENCH_ROOTFS_WRITE'
BENCH_ROOTFS_READ='$BENCH_ROOTFS_READ'
BENCH_RAM_WRITE='$BENCH_RAM_WRITE'
BENCH_RAM_READ='$BENCH_RAM_READ'
BENCH_CUSTOMFS_WRITE='$BENCH_CUSTOMFS_WRITE'
BENCH_CUSTOMFS_READ='$BENCH_CUSTOMFS_READ'
BENCH_CPU_TEMP_START='$BENCH_CPU_TEMP_START'
BENCH_CPU_TEMP_END='$BENCH_CPU_TEMP_END'
BENCH_NET_LAN_SPEED='$BENCH_NET_LAN_SPEED'
_EOF_
}
Upload_Survey(){
if grep -q '^[[:blank:]]*SURVEY_OPTED_IN=1$' /boot/dietpi.txt
then
/boot/dietpi/dietpi-survey 1
elif G_WHIP_YESNO 'To upload and compare your results against other users, you must be opted in to the DietPi-Survey.\n\nWould you like to run DietPi-Survey now, allowing you to opt in?'
then
/boot/dietpi/dietpi-survey
fi
}
CPU_Benchmark(){
G_DIETPI-NOTIFY 2 "Running CPU benchmark with max value of 1000000 over $G_HW_CPU_CORES cores, please wait..."
cat << _EOF_ > bench
#!/bin/bash
target_max_int=$CPUBENCH_INT_MAX
cores=$G_HW_CPU_CORES
int_split=\$(( \$target_max_int / \$cores ))
aStart_Int=()
aEnd_Int=()
# Split the max int target based on total cores
for ((i=0; i<\$cores; i++))
do
aEnd_Int[\$i]=\$(( (\$i + 1) * \$int_split ))
aStart_Int[\$i]=\$(( \${aEnd_Int[\$i]} - \$int_split ))
echo \${aStart_Int[\$i]} \${aEnd_Int[\$i]}
done
Run_Bench(){
while (( \${aStart_Int[\$1]} < \${aEnd_Int[\$1]} ))
do
((aStart_Int[\$1]++))
done
}
# Launch benchmark threads
for ((i=0; i<\$cores; i++))
do
Run_Bench \$i &
done
# Wait for jobs to finish
for job in \$(jobs -p)
do
echo \$job
wait \$job
done
_EOF_
G_EXEC chmod +x bench
sync
G_SLEEP 1
BENCH_CPU_TEMP_START=$(G_OBTAIN_CPU_TEMP)
{ time -p ./bench; } 2> bench_result
BENCH_CPU_TEMP_END=$(G_OBTAIN_CPU_TEMP)
BENCH_CPU=$(mawk '/real/{print $2;exit}' bench_result)
(( $SHOW_RESULTS )) || return 0
G_WHIP_MSG "CPU benchmark results:\n
- Total time = $BENCH_CPU seconds
- Value to reach = $CPUBENCH_INT_MAX
- CPU temps = Start: ${BENCH_CPU_TEMP_START} °C | End: ${BENCH_CPU_TEMP_END} °C
\n\nNB: A lower 'Total time' is faster"
}
Filesystem_Benchmark(){
[[ -d $FP_BENCHFILE ]] || G_EXEC mkdir "$FP_BENCHFILE" # Failsafe
local min_benchmark_size=10
local max_benchmark_size=$(( $(G_CHECK_FREESPACE "$FP_BENCHFILE") - 50 )) # Assure 50 MiB stays free
local benchmark_file_name='dietpi-benchmark_testfile'
FP_BENCHFILE="${FP_BENCHFILE%/}/$benchmark_file_name"
# Obtain user benchmark size
if (( $BENCH_FILESIZE == 0 ))
then
G_WHIP_DEFAULT_ITEM=$min_benchmark_size
G_WHIP_INPUTBOX "Please enter a filesize test value (MiB). A value of 100 is recommended.
- Minimum value: $min_benchmark_size
- Maximum possible value: $max_benchmark_size" && BENCH_FILESIZE=$G_WHIP_RETURNED_VALUE
fi
# Sanity
disable_error=1 G_CHECK_VALIDINT "$BENCH_FILESIZE" "$min_benchmark_size" || BENCH_FILESIZE=$min_benchmark_size
(( $BENCH_FILESIZE > $max_benchmark_size )) && BENCH_FILESIZE=$max_benchmark_size
# Run benchmark
G_DIETPI-NOTIFY 2 "Running read/write benchmark on $FP_BENCHFILE ($BENCH_FILESIZE MiB)"
G_DIETPI-NOTIFY 2 'Testing seq write speed, please wait...'
G_SLEEP 1
local bench_write_result=$(dd bs=4K count=$(( $BENCH_FILESIZE * 256 )) if=/dev/zero of="$FP_BENCHFILE" conv=fdatasync 2>&1 | mawk '/copied/{printf "%.0f",$1/$8/1024^2;exit}')
G_DIETPI-NOTIFY 0 "Result: $bench_write_result MiB/s"
G_DIETPI-NOTIFY 2 'Clearing filesystem cache...'
sync
echo 3 > /proc/sys/vm/drop_caches
G_DIETPI-NOTIFY 2 'Testing seq read speed, please wait...'
G_SLEEP 1
local bench_read_result=$(dd bs=4K count=$(( $BENCH_FILESIZE * 256 )) if="$FP_BENCHFILE" of=/dev/null 2>&1 | mawk '/copied/{printf "%.0f",$1/$8/1024^2;exit}')
G_DIETPI-NOTIFY 0 "Result: $bench_read_result MiB/s"
[[ -f $FP_BENCHFILE ]] && G_EXEC rm "$FP_BENCHFILE"
# RootFS
if [[ $FP_BENCHFILE == "/$benchmark_file_name" ]]
then
BENCH_ROOTFS_WRITE=$bench_write_result
BENCH_ROOTFS_READ=$bench_read_result
# RAM
elif [[ $FP_BENCHFILE == "/tmp/$benchmark_file_name" ]]
then
BENCH_RAM_WRITE=$bench_write_result
BENCH_RAM_READ=$bench_read_result
# Custom
else
BENCH_CUSTOMFS_WRITE=$bench_write_result
BENCH_CUSTOMFS_READ=$bench_read_result
fi
(( $SHOW_RESULTS )) || return 0
G_WHIP_MSG "Filesystem benchmark results:\n
- File path = $FP_BENCHFILE
- Test size = $BENCH_FILESIZE MiB
- WRITE = $bench_write_result MiB/s
- READ = $bench_read_result MiB/s"
}
Benchmark_Survey(){
SHOW_RESULTS=0
[[ -d '/var/lib/dietpi/dietpi-benchmark' ]] || G_EXEC mkdir /var/lib/dietpi/dietpi-benchmark
if (( $G_INTERACTIVE ))
then
G_WHIP_YESNO "$G_PROGRAM_NAME will now run the following benchmarks:\n - CPU performance\n - RootFS read/write performance\n - RAM read/write performance
\nThe test duration depends on hardware specs, ranging from a few seconds up to a few minutes on slower hardware like Raspberry Pi 1 and Zero (1) models.
\nIf you are opted in to the DietPi-Survey, your scores will uploaded automatically.
You can compare results against other users and hardware using the following link:\n - https://dietpi.com/survey#benchmark
\nPlease select 'Ok' to begin the benchmark tests." || { G_DIETPI-NOTIFY 2 'Benchmark aborted'; exit 0; }
fi
G_DIETPI-NOTIFY 2 'Running benchmark suite tests, please wait...'
CPU_Benchmark
# RAM
if df -t tmpfs /tmp &> /dev/null
then
# Apply performance CPU governor to avoid low frequency affecting RAM I/O results: https://github.com/MichaIng/DietPi/issues/5039#issuecomment-1021459310
local acpufreq
mapfile -t acpufreq < <(find /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor 2> /dev/null)
if [[ ${acpufreq[0]} ]]
then
G_DIETPI-NOTIFY 2 'Temporarily applying performance CPU governor for RAM I/O benchmark...'
for i in "${acpufreq[@]}"
do
echo 'performance' > "$i"
done
fi
FP_BENCHFILE='/tmp'
BENCH_FILESIZE=$(mawk '/^MemFree:/{printf "%.0f",$2/2048;exit}' /proc/meminfo) # Assure 50% of physical mem stays free, so swapping can be ruled out: KiB => MiB / 2
Filesystem_Benchmark
if [[ ${acpufreq[0]} ]]
then
G_DIETPI-NOTIFY 2 'Restoring original CPU governor...'
/boot/dietpi/func/dietpi-set_cpu
fi
else
G_DIETPI-NOTIFY 1 '/tmp does not seem to be mounted as tmpfs (RAMdisk). Skipping RAM I/O benchmark...'
fi
# RootFS
FP_BENCHFILE='/'
BENCH_FILESIZE=100
Filesystem_Benchmark
SHOW_RESULTS=1
G_WHIP_MSG "Benchmarks completed:
- CPU performance : Duration = $BENCH_CPU seconds (lower is faster)
- CPU temps : Idle = ${BENCH_CPU_TEMP_START} °C | Full load = ${BENCH_CPU_TEMP_END} °C
- RootFS I/O : Write = $BENCH_ROOTFS_WRITE MiB/s | Read = $BENCH_ROOTFS_READ MiB/s
- RAM I/O : Write = $BENCH_RAM_WRITE MiB/s | Read = $BENCH_RAM_READ MiB/s
Compare these results online with other users, using the link below:
- https://dietpi.com/survey#benchmark"
}
Benchmark_Lan_Server(){
G_AG_CHECK_INSTALL_PREREQ iperf
G_THREAD_START iperf -s
G_WHIP_MSG "Network benchmark is now running in 'server mode'. Please use another DietPi system to connect as a client and begin the test.
- Server IP = $(G_GET_NET ip)\n\nWhen the client has finished, select 'Ok' to stop the server."
killall -w iperf
G_THREAD_WAIT
}
Benchmark_Lan_Client(){
G_WHIP_INPUTBOX 'Please enter the IP address of the system running the network benchmark server:\n - E.g.: 192.168.0.100' || return 0
IPERF_SERVER_IP=$G_WHIP_RETURNED_VALUE
G_AG_CHECK_INSTALL_PREREQ iperf
G_DIETPI-NOTIFY 2 "Benchmarking network performance to $IPERF_SERVER_IP, please wait..."
BENCH_NET_LAN_SPEED=$(iperf -c "$IPERF_SERVER_IP" -p 5001 -t 5 -y C | sed 's/.*,//g')
if disable_error=1 G_CHECK_VALIDINT "$BENCH_NET_LAN_SPEED"
then
BENCH_NET_LAN_SPEED=$(( $BENCH_NET_LAN_SPEED / 8 / 1024**2 ))
G_WHIP_MSG "Network LAN benchmark completed:\n - Transfer rate = $BENCH_NET_LAN_SPEED MiB/s"
else
G_WHIP_MSG 'Network LAN benchmark failed, please verify:\n - Server is running on the other system\n - Server IP address is correct'
BENCH_NET_LAN_SPEED='Not tested'
fi
}
#/////////////////////////////////////////////////////////////////////////////////////
# Main Loop
#/////////////////////////////////////////////////////////////////////////////////////
#-----------------------------------------------------------------------------------
# Run at highest CPU and I/O priority
renice -n -19 $$
ionice -p $$ -c 1 -n 0
#-----------------------------------------------------------------------------------
# Init vars for sourcing
if (( $INPUT == 0 ))
then
Save_Results
# LAN bench server
elif (( $INPUT == 3 ))
then
Benchmark_Lan_Server
# Run benchmarks
else
#-----------------------------------------------------------------------------------
/boot/dietpi/dietpi-services stop
#-----------------------------------------------------------------------------------
# Reuse existing results if done
Load_Results
#-----------------------------------------------------------------------------------
if (( $INPUT == 1 ))
then
Filesystem_Benchmark
elif (( $INPUT == 2 ))
then
Benchmark_Survey
elif (( $INPUT == 4 ))
then
Benchmark_Lan_Client
fi
#-----------------------------------------------------------------------------------
# Export results data for other scripts:
Save_Results
#-----------------------------------------------------------------------------------
# Upload if in survey, else, prompt
Upload_Survey
#-----------------------------------------------------------------------------------
/boot/dietpi/dietpi-services start
#-----------------------------------------------------------------------------------
fi
#-----------------------------------------------------------------------------------
exit 0
#-----------------------------------------------------------------------------------
}