-
Notifications
You must be signed in to change notification settings - Fork 78
/
sbc-bench.sh
executable file
·10041 lines (9587 loc) · 433 KB
/
sbc-bench.sh
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
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
Version=0.9.68
InstallLocation=/usr/local/src # change to /tmp if you want tools to be deleted after reboot
Main() {
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/vc/bin
PathToMe="$( cd "$(dirname "$0")" || exit 1 ; pwd -P )/${0##*/}"
unset LC_ALL LC_MESSAGES LC_NUMERIC LANGUAGE LANG 2>/dev/null # prevent localisation of decimal points and similar stuff
NO_COLOR="${NO_COLOR:-}"
Netio="${Netio:-}"
Smartpower="${Smartpower:-}"
Linpack="${Linpack:-}"
# use colours and bold when outputting to a terminal
CheckTerminal
# The following allows to use sbc-bench on real ARM devices where for
# whatever reasons a fake /usr/bin/vcgencmd is lying around -- see for
# an example here: https://github.com/ThomasKaiser/sbc-bench/pull/13
VCGENCMD=$(command -v vcgencmd)
if [ -z "${USE_VCGENCMD}" ] && [ -x "${VCGENCMD}" ]; then
# this seems to be a Raspberry Pi where we need to query
# ThreadX on the VC via vcgencmd to get real information
# Double check via device-tree compatible string:
[ -f /proc/device-tree/compatible ] && \
grep -a -q raspberrypi /proc/device-tree/compatible
if [ $? -eq 0 ]; then
USE_VCGENCMD=true
else
USE_VCGENCMD=false
fi
else
USE_VCGENCMD=false
fi
ProcCPUFile="${CPUINFOFILE:-/proc/cpuinfo}"
[ -r "${ProcCPUFile}" ] && ProcCPU="$(cat "${ProcCPUFile}")"
[ -r /etc/os-release ] && source /etc/os-release
# check in which mode we're supposed to run
while getopts 'uSchjkmtTrRsgNPG' c ; do
case ${c} in
m)
# monitoring mode
SleepInterval=${2:-5}
if [ -n "${Netio}" ] && [ -z "${NetioConsumptionFile}" ]; then
QueryNetioDevice
if [ "X${OutputCurrents[*]}" != "X" ]; then
# We are in Netio monitoring mode as such provide consumption info as well
echo -e "Power monitoring on socket ${NetioSocket} of ${NetioName} (Netio ${NetioModel}, FW v${Firmware}, XML API v${XmlVer}, ${InputVoltage}V @ ${Frequency}Hz)\n"
CreateTempDir
NetioConsumptionFile="${TempDir}/netio.current"
echo -n $(( $(awk '{printf ("%0.0f",$1/10); }' <<<"${OutputCurrent[$(( ${NetioSocket} - 1 ))]}" ) * 10 )) >"${NetioConsumptionFile}"
export NetioConsumptionFile
NetioInterval=$(LC_ALL=C awk '{printf ("%0.1f",$1/2); }' <<<"${SleepInterval}")
NetioSamples=$(( SleepInterval * 3 ))
/bin/bash "${PathToMe}" -N ${NetioDevice} ${NetioSocket} ${NetioConsumptionFile} "${NetioInterval}" "${NetioSamples}" >/dev/null 2>&1 &
NetioMonitoringPID=$!
fi
fi
MonitorMode=TRUE
MonitorBoard
[ -n "${Netio}" ] && [ -z "${NetioConsumptionFile}" ] && kill ${NetioMonitoringPID} >/dev/null 2>&1
exit 0
;;
c)
# Run Cpuminer test (NEON/SSE/AVX)
ExecuteCpuminer=yes
;;
s)
# Run Stockfish test (NEON/SSE/AVX/RAM)
NeuralNetwork=$2
ExecuteStockfish=yes
;;
S)
# check storage, only for testing, will disappear later
DMESG="$(dmesg | grep "mmc")"
SMARTDrives="$(ls /dev/sd* /dev/nvme* 2>/dev/null)"
if [ "X${SMARTDrives}" != "X" ]; then
# warn about absence of smartctl and running not as root only when needed
command -v smartctl >/dev/null 2>&1 || echo -e "${BOLD}Warning: smartmontools not installed${NC}\n" >&2
[ ${UID} = 0 ] || echo -e "${BOLD}Warning: to query all drive info this tool needs to be run as root${NC}\n" >&2
fi
CheckStorage | sed 's/000Mbps/Gbps/'
exit 0
;;
h)
# print help
DisplayUsage
exit 0
;;
u)
# replace script with latest version from Github
UpdateMe
exit 0
;;
j|r)
# Jeff Geerling or Jean-Luc Aufranc mode. Help in reviewing devices
REVIEWMODE=true
SleepInterval=${2:-5}
RunBenchmarks=TRUE
[ ${UID} = 0 ] || { echo -e "${BOLD}Warning: for useable results this tool needs to be run as root${NC}\n" >&2 ; exit 1 ; }
ProvideReviewInfo
exit 0
;;
R)
# Review mode w/o basic benchmarking and thermal throttling tests
REVIEWMODE=true
SleepInterval=${2:-5}
[ ${UID} = 0 ] || { echo -e "${BOLD}Warning: for useable results this tool needs to be run as root${NC}\n" >&2 ; exit 1 ; }
ProvideReviewInfo
exit 0
;;
k)
# Kernel info. Check kernel version against https://endoflife.date/linux
# and issue warnings if used kernel is not an official one but vendor/BSP
PrintKernelInfo
exit 0
;;
t|T)
# temperature tests sufficient for heatsink/fan and throttling settings testing
# 2nd argument (integer in degree C) is the value we wait for the board to cool
# down prior to next test
TargetTemp=${2:-50}
[ ${UID} = 0 ] || { echo -e "${BOLD}Warning: for useable results this tool needs to be run as root${NC}\n" >&2 ; exit 1 ; }
TempTest
exit 0
;;
g)
# graph performance chart instead of doing standard 7-zip benchmarks, thereby
# walking through different cpufreq OPP. An additional parameter in taskset's
# --cpu-list format can be provided, eg. '-g 0' to graph only cpu0 or '-g 4'
# to graph only cpu4 (which might be an A72 on big.LITTLE systems). Mixing
# CPUs from different clusters (e.g. '-g 0,4' on a RK3399) will result in
# garbage since big and little cores have other cpufreq OPP.
# 3 special modes exist: cores, clusters and all.
# * '-g cores' will test single-threaded through cluster's cores (0 and 4 on
# RK3399, 0 and 2 on S922X and so on)
# * '-g clusters' tests all cores of each cluster (0-3 and 4-5 on RK3399,
# 0-1 and 2-5 on S922X and so on)
# * '-g all' performs both tests from above and then runs the test on all
# cores as well. This will take ages.
PlotCpufreqOPPs=yes
CPUList=${2}
[ "X${CPUList}" = "X" ] || [ "X${CPUList}" = "Xall" ] || [ "X${CPUList}" = "Xcores" ] || [ "X${CPUList}" = "Xclusters" ] || [ "X${CPUList}" = "Xcoreclusters" ] \
|| taskset -c ${CPUList} echo "foo" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo -e "\nInvalid option \"-g ${CPUList}\". Please check taskset manual page for --cpu-list format" >&2
DisplayUsage
exit 1
fi
;;
G)
# Geekbench piggyback mode. Geekbench lacks sanity checks (measuring
# clockspeeds) and environment monitoring (too much background activity
# or throttling for example).
MODE="gb"
;;
P)
# Phoronix Test Suite piggyback mode. PTS lacks sanity checks (measuring
# clockspeeds) and environment monitoring (too much background activity
# or throttling for example). You need to install Phoronix Test Suite by
# yourself (see https://www.phoronix-test-suite.com/?k=downloads) and run
# 'phoronix-test-suite batch-setup' once to configure batch operation mode:
#
# Save test results when in batch mode (Y/n): y
# Open the web browser automatically when in batch mode (y/N): n
# Auto upload the results to OpenBenchmarking.org (Y/n): Y
# Prompt for test identifier (Y/n): n
# Prompt for test description (Y/n): n
# Prompt for saved results file-name (Y/n): n
# Run all test options (Y/n): n
#
# If you want PTS progress info use 'tail -f /tmp/sbc-bench.*/temp.log'
# in another shell. You'll need this anyway since if 'Run all test options'
# has been answered with no, then PTS of course expects you giving manual
# feedback even if in batch-benchmark mode.
#
# root@rock-5b:/tmp/sbc-bench.Pvhatc# tail -f temp.log
# SQLite 3.30.1:
# pts/sqlite-2.1.0
# Disk Test Configuration
# 1: 1
# 2: 8
# 3: 32
# 4: 64
# 5: 128
# 6: Test All Options
# ** Multiple items can be selected, delimit by a comma. **
#
# In the invoking shell you need to enter the desired config then PTS
# proceeds.
MODE="pts"
shift
PTSArguments="$*"
;;
N)
# internal Netio monitor mode. Do not use this unless you really know
# what you're doing. Requires enabled 'XML API' on your device (read-only
# w/o password: https://www.netio-products.com/en/glossary/xml-over-https)
# Needs address/name and socket number and a file where results will be
# written to. For example '-N powerbox-1.local 2 /tmp/my-consumption' if
# your Netio device is accessible as powerbox-1.local, this device is
# plugged into its 2nd socket and you want consumption to be written to
# /tmp/my-consumption where it can be picked up by tools like RPi Monitor.
# The last 2 arguments are optional: sleep time (defaults to 0.8) and
# count of samples (defaults to 30). The defaults already put significant
# load on the device (compare http://ix.io/3E91 and http://ix.io/3Ebd) so
# to monitor idle consumption better choose 4.8 and 30 and deal with a 150
# seconds average value.
MonitorNetio "$2" "$3" "$4" "$5" "$6"
exit 0
;;
*)
# invalid flags
DisplayUsage
exit 1
;;
esac
done
[ ${UID} = 0 ] || echo -e "${BOLD}Warning: when not being executed as root strange things will happen${NC}\n" >&2
# ensure other sbc-bench instances are terminated
for PID in $( (pgrep -f "${PathToMe}" ; jobs -p) | sort | uniq -u) ; do
if [ ${PID} -ne $$ ]; then
kill ${PID} 2>/dev/null
fi
done
# do a normal release check only if not in PTS or GB mode, in review mode warn if
# distro is not rather recent
if [ "X${MODE}" = "Xpts" ] || [ "X${MODE}" = "Xgb" ]; then
:
elif [ "X${REVIEWMODE}" = "Xtrue" ]; then
CheckOSRelease ForReview
else
CheckOSRelease
fi
unset SPACING
CreateTempDir
[ -f /sys/devices/system/cpu/cpufreq/policy0/scaling_governor ] && \
read OriginalCPUFreqGovernor </sys/devices/system/cpu/cpufreq/policy0/scaling_governor 2>/dev/null
[ "${OriginalCPUFreqGovernor}" = "ondemand" ] && \
io_is_busy=( $(find /sys/devices/system/cpu/cpufreq -name io_is_busy | while read ; do cat "${REPLY}"; done) )
CheckLoadAndDmesg
BasicSetup performance >/dev/null 2>&1
GovernorState="$(HandleGovernors | grep -v cpufreq-policy)"
[ "X${GovernorState}" != "X" ] && echo -e "Status of performance related governors found below /sys (w/o cpufreq):\n${GovernorState}\n"
GetTempSensor
[ "X${MODE}" = "Xpts" ] && CheckPTS
InstallPrerequisits
[ "X${MODE}" = "Xgb" ] && CheckGB
InitialMonitoring
CheckClockspeedsAndSensors
CheckTimeInState before
if [ "${PlotCpufreqOPPs}" = "yes" ]; then
PlotPerformanceGraph
else
CheckNetio
[ "X${MODE}" = "Xpts" ] || [ "X${MODE}" = "Xgb" ] || RunTinyMemBench
RunRamlat
if [ "X${MODE}" = "Xpts" ]; then
RunPTS
elif [ "X${MODE}" = "Xgb" ]; then
RunGB
else
RunOpenSSLBenchmark "128 192 256"
Run7ZipBenchmark
if [ "${ExecuteCpuminer}" = "yes" ] || [ "X${MODE}" = "Xextensive" ]; then
if [ -x "${InstallLocation}"/cpuminer-multi/cpuminer ]; then
ExecuteCpuminer=yes
RunCpuminerBenchmark
else
ExecuteCpuminer=no
echo -e "\x08\x08 Done.\n(${InstallLocation}/cpuminer-multi/cpuminer missing or not executable)...\c"
fi
fi
if [ "${ExecuteStockfish}" = "yes" ] || [ "X${MODE}" = "Xextensive" ]; then
if [ -x "${InstallLocation}/Stockfish-sf_15/src/stockfish" ]; then
ExecuteStockfish=yes
RunStockfishBenchmark
else
ExecuteStockfish=no
echo -e "\x08\x08 Done.\n(${InstallLocation}/Stockfish-sf_15/src/stockfish missing or not executable)...\c"
fi
fi
fi
fi
CheckTimeInState after
CheckClockspeedsAndSensors # test again loaded system after heating the SoC to the max
SummarizeResults
UploadResults
CheckAgeOfScript
BasicSetup ${OriginalCPUFreqGovernor} >/dev/null 2>&1
} # Main
CheckTerminal() {
# Check if we're outputting to a terminal. If yes try to use bold and colors for messages
# unless NO_COLOR is exported by the user and set to 1: https://no-color.org
if test -t 1; then
ncolors=$(tput colors)
if [ -n "${ncolors}" ] && [ "${ncolors}" -ge 8 ] && [ "X${NO_COLOR}" != "X1" ]; then
BOLD="$(tput bold)"
NC='\033[0m' # No Color
LGREEN='\033[1;32m'
LRED='\e[0;91m'
fi
fi
} # CheckTerminal
UpdateMe() {
# function to replace this script with latest version from here:
# https://raw.githubusercontent.com/ThomasKaiser/sbc-bench/master/sbc-bench.sh
# Also check/update the github projects except of stockfish since there we use
# a static and not latest version
[ -w "${PathToMe}" ] || { echo "Permission problem accessing ${PathToMe}. Wrong user? Aborting." >&2 ; exit 1 ; }
command -v curl >/dev/null 2>&1 || { echo "curl not found. Please install and try again. Aborting." >&2 ; exit 1 ; }
TempFile="$(mktemp /tmp/update-sbc-bench.XXXXXX)"
[ -w "${TempFile}" ] || { echo "Temp file creation not possible. Aborting." >&2 ; exit 1 ; }
curl -s "https://raw.githubusercontent.com/ThomasKaiser/sbc-bench/master/sbc-bench.sh" >"${TempFile}" \
|| { echo "Can not access Github. Network problem? Aborting." >&2 ; exit 1 ; }
VersionFromInternet="$(head "${TempFile}" | awk -F"=" '/^Version/ {print $2}')"
VersionCompare="$(echo -e "${VersionFromInternet}\n${Version}" | sort -V 2>/dev/null | tail -n1)"
if [ "X${VersionFromInternet}" = "X" ]; then
echo -e "Not able to download from Github. Updating not possible." >&2
exit 1
elif [ "X${Version}" = "X${VersionFromInternet}" ]; then
echo -e "Replaced ${Version} with ${Version} from Github...\c"
elif [ "X${VersionCompare}" = "X${VersionFromInternet}" ]; then
echo -e "Upgraded from ${Version} to ${VersionFromInternet}...\c"
elif [ "X${VersionCompare}" = "X${Version}" ]; then
echo -e "Downgraded from ${Version} to ${VersionFromInternet}...\c"
fi
cat "${TempFile}" >"${PathToMe}" && rm "${TempFile}"
echo -e "\x08\x08 Done."
# Only try to update git projects if git is already installed
command -v git >/dev/null 2>&1 || exit 0
for GitProject in mhz ramspeed tinymembench cpuminer-multi cpufetch p7zip ; do
if [ -x "${InstallLocation}/${GitProject}" ]; then
if [ -r "${InstallLocation}/${GitProject}/.git/config" ]; then
GitURL="$(awk -F" = " '/url = / {print $2}' "${InstallLocation}/${GitProject}/.git/config")"
echo -e "Checking/updating ${GitURL}...\c"
else
echo -e "Checking/updating ${GitProject} from Github...\c"
fi
cd "${InstallLocation}/${GitProject}" || exit 1
GitResult="$(git pull 2>/dev/null)"
case "${GitResult}" in
*"up to date"*)
echo -e "\x08\x08 ${GitResult}"
;;
*)
case ${GitProject} in
cpuminer-multi)
rm "${InstallLocation}"/cpuminer-multi/.do-not-try-to-build-again 2>/dev/null
./build.sh >/dev/null 2>&1
case $? in
0)
echo -e "\x08\x08 Done."
;;
*)
echo -e "\x08\x08 Failed."
;;
esac
;;
*)
make clean >/dev/null 2>&1
make >/dev/null 2>&1
echo -e "\x08\x08 Done."
;;
esac
esac
fi
done
} # UpdateMe
CheckAgeOfScript() {
# checks modification of this file on disk, compares to 'time now' and if difference
# is a month or more then suggests running 'sbc-bench -u' for an update check
FileTime=$(stat -c %Y -- "${PathToMe}" 2>/dev/null)
TimeNow=$(date "+%s")
FileAge=$(( $(( ${TimeNow} - ${FileTime} )) / 86400 ))
if [ ${FileAge:-0} -ge 30 ]; then
[ "X${SUDO_USER}" != "X" ] && Sudoprefix="sudo "
echo -e "\nJust for your information: this script's version on disk is ${FileAge} days old."
echo -e "Maybe checking for an update: ${BOLD}${Sudoprefix}${PathToMe} -u${NC}\n"
fi
} # CheckAgeOfScript
snore() {
# https://blog.dhampir.no/content/sleeping-without-a-subprocess-in-bash-and-how-to-sleep-forever
local IFS
[[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
{
# workaround for MacOS and similar systems
local fifo
fifo=$(mktemp -u)
mkfifo -m 700 "$fifo"
exec {_snore_fd}<>"$fifo"
rm "$fifo"
}
read ${1:+-t "$1"} -u $_snore_fd || :
} # snore
GetARMCore() {
# List originally obtained from util-linux project but later appended by looking at
# https://github.com/gcc-mirror/gcc/blob/master/gcc/config/aarch64/aarch64-cores.def
# and https://github.com/llvm/llvm-project/blob/release/15.x/llvm/lib/Support/Host.cpp
# and https://github.com/torvalds/linux/blob/master/arch/arm64/include/asm/cputype.h
# and https://github.com/Dr-Noob/cpufetch/blob/master/src/arm/uarch.c
# and https://github.com/pytorch/cpuinfo/blob/main/src/arm/linux/midr.c
# and https://github.com/hrw/arm-socs-table/blob/main/data/cpu_cores.yml
grep "${1}/${2}:" <<<"41:Arm
41/810:ARM810
41/920:ARM920
41/922:ARM922
41/926:ARM926
41/940:ARM940
41/946:ARM946
41/966:ARM966
41/a20:ARM1020
41/a22:ARM1022
41/a26:ARM1026
41/b02:ARM11 MPCore
41/b36:ARM1136
41/b56:ARM1156
41/b76:ARM1176
41/c05:Cortex-A5
41/c07:Cortex-A7
41/c08:Cortex-A8
41/c09:Cortex-A9
41/c0c:Cortex-A12
41/c0d:Cortex-A17
41/c0e:Cortex-A17
41/c0f:Cortex-A15
41/c14:Cortex-R4
41/c15:Cortex-R5
41/c17:Cortex-R7
41/c18:Cortex-R8
41/c20:Cortex-M0
41/c21:Cortex-M1
41/c23:Cortex-M3
41/c24:Cortex-M4
41/c27:Cortex-M7
41/c60:Cortex-M0+
41/d01:Cortex-A32
41/d02:Cortex-A34
41/d03:Cortex-A53
41/d04:Cortex-A35
41/d05:Cortex-A55
41/d06:Cortex-A65
41/d07:Cortex-A57
41/d08:Cortex-A72
41/d09:Cortex-A73
41/d0a:Cortex-A75
41/d0b:Cortex-A76
41/d0c:Neoverse-N1
41/d0d:Cortex-A77
41/d0e:Cortex-A76AE
41/d13:Cortex-R52
41/d15:Cortex-R82
41/d16:Cortex-R52+
41/d20:Cortex-M23
41/d21:Cortex-M33
41/d22:Cortex-M55
41/d23:Cortex-M85
41/d40:Neoverse-V1
41/d41:Cortex-A78
41/d42:Cortex-A78AE
41/d43:Cortex-A65AE
41/d44:Cortex-X1
41/d46:Cortex-A510
41/d47:Cortex-A710
41/d48:Cortex-X2
41/d49:Neoverse-N2
41/d4a:Neoverse-E1
41/d4b:Cortex-A78C
41/d4c:Cortex-X1C
41/d4d:Cortex-A715
41/d4e:Cortex-X3
41/d4f:Neoverse-V2
41/d80:Cortex-A520
41/d81:Cortex-A720
41/d82:Cortex-X4
41/d84:Neoverse-V3
41/d85:Cortex-X925
41/d87:Cortex-A725
41/d8e:Neoverse-N3
42:Broadcom
42/00f:Broadcom Brahma B15
42/100:Broadcom Brahma B53
42/516:Broadcom ThunderX2
43:Cavium
43/0a0:Cavium ThunderX
43/0a1:Cavium ThunderX 88XX
43/0a2:Cavium ThunderX 81XX
43/0a3:Cavium ThunderX 83XX
43/0af:Cavium ThunderX2 99xx
43/0b0:Cavium OcteonTX2
43/0b1:Cavium OcteonTX2 98XX
43/0b2:Cavium OcteonTX2 96XX
43/0b3:Cavium OcteonTX2 95XX
43/0b4:Cavium OcteonTX2 95XXN
43/0b5:Cavium OcteonTX2 95XXMM
43/0b6:Cavium OcteonTX2 95XXO
43/0b8:Cavium ThunderX3 T110
44:DEC
44/a10:DEC SA110
44/a11:DEC SA1100
46:Fujitsu
46/001:A64FX
48:HiSilicon
48/d01:TaiShan v110
48/d02:TaiShan v120
48/d03:TaiShan v130
48/d40:HiSilicon-A76
48/d41:HiSilicon-A77
48/d42:HiSilicon-A710
00/d02:HiSilicon-1910
49:Infineon
4d:Motorola/Freescale
4e:NVidia
4e/000:NVidia Denver
4e/003:NVidia Denver 2
4e/004:NVidia Carmel
50:APM
50/000:APM X-Gene
51:Qualcomm
51/001:Qualcomm Oryon 1
51/002:Qualcomm Oryon 2
51/00f:Qualcomm Scorpion
51/02d:Qualcomm Scorpion
51/04d:Qualcomm Krait
51/06f:Qualcomm Krait
51/201:Qualcomm Kryo
51/205:Qualcomm Kryo
51/211:Qualcomm Kryo
51/800:Qualcomm Falkor V1/Kryo
51/801:Qualcomm Kryo V2
51/802:Qualcomm Kryo 3XX Gold
51/803:Qualcomm Kryo 3XX Silver
51/804:Qualcomm Kryo 4XX Gold
51/805:Qualcomm Kryo 4XX Silver
51/c00:Qualcomm Falkor
51/c01:Qualcomm Saphira
53:Samsung
53/001:Samsung Exynos-m1
53/002:Samsung Exynos-m3
53/003:Samsung Exynos-m4
53/004:Samsung Exynos-m5
56:Marvell
56/131:Marvell Feroceon 88FR131
56/581:Marvell PJ4/PJ4b
56/584:Marvell PJ4B-MP
61:Apple
61/000:Apple Swift
61/001:Apple Cyclone
61/002:Apple Typhoon
61/003:Apple Typhoon/Capri
61/004:Apple Twister
61/005:Apple Twister/Elba/Malta
61/006:Apple Hurricane
61/007:Apple Hurricane/Myst
61/008:Apple Monsoon
61/009:Apple Mistral
61/00b:Apple Vortex
61/00c:Apple Tempest
61/00f:Apple Tempest-M9
61/010:Apple Vortex-Aruba
61/011:Apple Tempest-Aruba
61/012:Apple Lightning
61/013:Apple Thunder
61/020:Apple Icestorm A14
61/021:Apple Firestorm A14
61/022:Apple Icestorm M1
61/023:Apple Firestorm M1
61/024:Apple Icestorm M1Pro
61/025:Apple Firestorm M1Pro
61/026:Apple Thunder-M10
61/028:Apple Icestorm M1Max
61/029:Apple Firestorm M1Max
61/030:Apple Blizzard A15
61/031:Apple Avalanche A15
61/032:Apple Blizzard M2
61/033:Apple Avalanche M2
61/034:Apple Blizzard M2Pro
61/035:Apple Avalanche M2Pro
61/036:Apple Sawtooth A16
61/037:Apple Everest A16
61/038:Apple Blizzard M2Max
61/039:Apple Avalanche M2Max
61/046:Apple Sawtooth M11
61/048:Apple Sawtooth M3Max
61/049:Apple Everest M3Max
61/000:Virtualized Apple Silicon
00/000:Virtualized Apple Silicon
66:Faraday
66/526:Faraday FA526
66/626:Faraday FA626
68:Huaxintong Semiconductor (HXT)
68/000:HXT Phecda
69:Intel
69/200:Intel i80200
69/210:Intel PXA250A
69/212:Intel PXA210A
69/242:Intel i80321-400
69/243:Intel i80321-600
69/290:Intel PXA250B/PXA26x
69/292:Intel PXA210B
69/2c2:Intel i80321-400-B0
69/2c3:Intel i80321-600-B0
69/2d0:Intel PXA250C/PXA255/PXA26x
69/2d2:Intel PXA210C
69/411:Intel PXA27x
69/41c:Intel IPX425-533
69/41d:Intel IPX425-400
69/41f:Intel IPX425-266
69/682:Intel PXA32x
69/683:Intel PXA930/PXA935
69/688:Intel PXA30x
69/689:Intel PXA31x
69/b11:Intel SA1110
69/c12:Intel IPX1200
6d:Microsoft
6d/d49:Azure Cobalt 100
70:Phytium
70/303:Phytium FTC310
70/660:Phytium FTC660
70/661:Phytium FTC661
70/662:Phytium FTC662
70/663:Phytium FTC663
70/664:Phytium FTC664
70/862:Phytium FTC862
c0:Ampere
c0/ac3:Ampere Ampere-1
c0/ac4:Ampere Ampere-1a" | cut -f2 -d:
} # GetARMCore
GetCoreType() {
# function that returns name of CPU cores on several platforms
# $1 is the CPU in question, 1st CPU is always cpu0
case ${CPUArchitecture} in
arm*|aarch*)
if [ -n "${ARMTypes}" ]; then
GetARMCore "${ARMTypes[$(( $1 * 2 ))]}" "${ARMTypes[$(( $(( $1 * 2 )) + 1 ))]}" | tail -n1
fi
;;
riscv*)
# TODO: newer kernels now expose more information so we could use this:
# (mvendorid corresponds to manufacturer's JEDEC ID)
# https://gist.github.com/ThomasKaiser/14002f473d354360bf6d87c652c209aa
# relying on uarch doesn't work with older RISC-V kernels since missing
grep -q '^uarch' <<< "${ProcCPU}"
case $? in
0)
awk -F": " '/^uarch/ {print $2}' <<< "${ProcCPU}" | sed -n $(( $1 + 1 ))p
;;
*)
awk -F": " '/^isa/ {print $2}' <<< "${ProcCPU}" | sed -n $(( $1 + 1 ))p
;;
esac
;;
loongarch*)
ModelName="$(awk -F": " '/^model name/ {print $2}' <<< "${ProcCPU}" | sed -n $(( $1 + 1 ))p)"
case ${ModelName} in
*3?5000*)
echo "LA464"
;;
*3?6000*)
echo "LA664"
;;
"")
# fallback to cpu model if existing
grep -q 'cpu model' <<< "${ProcCPU}" && awk -F": " '/^cpu model/ {print $2}' <<< "${ProcCPU}" | sed -n $(( $1 + 1 ))p
;;
*\(*)
# we use just the part in brackets: Loongson-3A R4 (Loongson-3A4000) @ 1500MHz
awk -F"[()]" '{print $2}' <<<"${ModelName}"
;;
*)
echo "${ModelName}"
;;
esac
;;
mips*)
awk -F": " '/^cpu model/ {print $2}' <<< "${ProcCPU}" | sed -n $(( $1 + 1 ))p
;;
x86_64)
# on hybrid x86 designs print core type
if [ ${#ClusterConfig[@]} -gt 1 ]; then
if [ $1 -lt ${ClusterConfig[1]} ]; then
echo "${PCores}"
else
echo "${ECores}"
fi
fi
;;
esac
} # GetCoreType
GetARMStepping() {
# Parse '^CPU variant|^CPU revision' fields from /proc/cpuinfo and transform them
# into 'Stepping' like lscpu does (the latter in older versions only showing info for
# cpu0 so partially useless on systems with different CPU clusters)
if [ -n "${ARMStepping}" ]; then
echo "r$(awk -Wposix '{printf("%d", $1)}' <<<${ARMStepping[$(( $1 * 2 ))]})p${ARMStepping[$(( $(( $1 * 2 )) + 1 ))]}"
fi
} # GetARMStepping
GetCPUInfo() {
# function that returns ARM/RISC-V core type in brackets if possible otherwise empty string
CoreType="$(GetCoreType $1)"
[ -n "${CoreType}" ] && echo " (${CoreType})"
} # GetCPUInfo
GetLastClusterCore() {
NextCore=${ClusterConfig[$1]}
[ "${NextCore}" = "" ] && NextCore=$(awk -F" " '/^CPU...:/ {print $2}' <<<"${LSCPU}")
echo -n $(( ${NextCore} - 1 ))
} # GetLastClusterCore
GetLastClusterCoreByType() {
NextCore=${ClusterConfigByCoreType[$1]}
[ "${NextCore}" = "" ] && NextCore=$(awk -F" " '/^CPU...:/ {print $2}' <<<"${LSCPU}")
echo -n $(( ${NextCore} - 1 ))
} # GetLastClusterCoreByType
BashBench(){
# quick integer performance assessment using a simple bash loop.
# Depends not only on CPU performance but also on bash version.
#
# 5.0.17 / E5-2665 @ 2.40GHz: 147485025
# 4.4.20 / Xeon Silver 4110 @ 3.00GHz: 64434988
# 5.0.3 / Xeon Silver 4110 @ 3.00GHz: 38958875
# 5.0.17 / N5100 @ 2.8GHz: 56864747
# 4.4.20 / Allwinner H3: 566944214
# 5.0.3 / BCM2711: 152325522
# 5.0.17 / Apple Firestorm: 28319838
# 5.2.15 / BCM2712 @ 3.0 GHz: 41210070
local i
StartTime=$(date +"%s%N")
i=0
while [ $i -lt 10000 ]
do
((i++))
done
FinishedTime=$(date +"%s%N")
RawTime=$(( ${FinishedTime} - ${StartTime} ))
case ${BASH_VERSION} in
5.*)
# multiply by 1.2 since this version seems faster
awk '{printf ("%0.0f",$1*1.2); }' <<<${RawTime}
;;
*)
echo -n ${RawTime}
;;
esac
} # BashBench
HandleGovernors() {
# check and report governors that might affect performance behaviour. Stuff like
# memory/GPU/NPU governors. On RK3588 it looks like this for example:
#
# Status of performance related governors found below /sys:
# cpufreq-policy0: ondemand / 408 MHz (conservative ondemand userspace powersave performance schedutil / 408 600 816 1008 1200 1416 1608 1800)
# cpufreq-policy4: ondemand / 408 MHz (conservative ondemand userspace powersave performance schedutil / 408 600 816 1008 1200 1416 1608 1800 2016 2208 2256 2304 2352 2400)
# cpufreq-policy6: ondemand / 408 MHz (conservative ondemand userspace powersave performance schedutil / 408 600 816 1008 1200 1416 1608 1800 2016 2208 2256 2304 2352 2400)
# dmc: dmc_ondemand / 528 MHz (rknpu_ondemand dmc_ondemand userspace powersave performance simple_ondemand / 528 1068 1560 2112)
# fb000000.gpu: simple_ondemand / 300 MHz (rknpu_ondemand dmc_ondemand userspace powersave performance simple_ondemand / 300 400 500 600 700 800 900 1000)
# fdab0000.npu: rknpu_ondemand / 1000 MHz (rknpu_ondemand dmc_ondemand userspace powersave performance simple_ondemand / 300 400 500 600 700 800 900 1000)
# use colours and bold when outputting to a terminal
[ -z "${BOLD}" ] && CheckTerminal
Governors="$(find /sys -name "*governor" 2>/dev/null | grep -E -v '/sys/module|cpuidle|watchdog')"
if [ "X${Governors}" = "X" ] || [ "${CPUArchitecture}" = "x86_64" ]; then
# skip if no governors found or on x86 where lots of cpufreq governors are
# listed to no avail since the actual work is done layers below.
return
elif [ "X$1" != "X" ]; then
# try to set all governors to $1
echo "${Governors}" | while read ; do
echo $1 >"${REPLY}" 2>/dev/null
done
# If in adjust mode we also tune ASPM since this can massively affect performance
# of components behind PCIe buses (NVMe SSDs, PCIe attached HBAs, NICs and so on)
if [ -w /sys/module/pcie_aspm/parameters/policy ] && [ -d /sys/bus/pci_express ]; then
read OriginalASPMSetting </sys/module/pcie_aspm/parameters/policy
echo $1 >/sys/module/pcie_aspm/parameters/policy 2>/dev/null
fi
return
fi
# process governors:
echo "${Governors}" | while read ; do
read Governor <"${REPLY}"
if [ "X${Governor}" != "X" ]; then
SysFSNode="$(sed 's/cpufreq\//cpufreq-/' <<<"${REPLY%/*}")"
AvailableGovernorsSysFSNode="$(ls -d "${REPLY%/*}"/*available_governors 2>/dev/null)"
AvailableFrequenciesSysFSNode="$(ls -d "${REPLY%/*}"/*available_frequencies 2>/dev/null)"
if [ -r "${REPLY%/*}/cpuinfo_cur_freq" ]; then
Curfreq=" / $(awk '{printf ("%0.0f",$1/1000); }' <"${REPLY%/*}/cpuinfo_cur_freq") MHz"
Divider=1000
elif [ -r "${REPLY%/*}/scaling_cur_freq" ]; then
Curfreq=" / $(awk '{printf ("%0.0f",$1/1000); }' <"${REPLY%/*}/scaling_cur_freq") MHz"
Divider=1000
elif [ -r "${REPLY%/*}/cur_freq" ]; then
read Rawfreq <"${REPLY%/*}/cur_freq"
if [ ${Rawfreq} -gt 10000000 ]; then
Curfreq=" / $(awk '{printf ("%0.0f",$1/1000000); }' <<<"${Rawfreq}") MHz"
Divider=1000000
else
Curfreq=" / $(awk '{printf ("%0.0f",$1/1000); }' <<<"${Rawfreq}") MHz"
Divider=1000
fi
else
Curfreq=""
fi
if [ -r "${AvailableGovernorsSysFSNode}" ]; then
# with some kernels powersave and performance are only listed as available
# after the governor itself has been set to these. So try this just not
# with cpufreq since there it always works as designed
case "${SysFSNode##*/}" in
*cpufreq*)
:
;;
*)
echo performance >"${REPLY}" 2>/dev/null
echo powersave >"${REPLY}" 2>/dev/null
echo "${Governor}" >"${REPLY}" 2>/dev/null
;;
esac
read AvailableGovernors <"${AvailableGovernorsSysFSNode}"
if [ "X${AvailableGovernors}" != "X${Governor}" ]; then
[ -r "${AvailableFrequenciesSysFSNode}" ] \
&& AvailableFrequencies=" / $(tr ' ' '\n' <"${AvailableFrequenciesSysFSNode}" | sort -n | sed '/^$/d' | awk "{printf (\"%0.0f\\n\",\$1/${Divider}); }" | tr '\n' ' ' | sed -e 's/\ $//' -e 's/^ //')" \
|| AvailableFrequencies=""
printf "${SysFSNode##*/}: "
grep -q "performance" <<<"${AvailableGovernors}"
GovStatus=$?
if [ ${GovStatus} -eq 0 ] && [ "X${Governor}" = "Xperformance" ]; then
echo -e "${LGREEN}performance${NC}${Curfreq} (${AvailableGovernors}${AvailableFrequencies})"
elif [ ${GovStatus} -eq 0 ] && [ "X${Governor}" != "Xperformance" ]; then
echo -e "${LRED}${Governor}${NC}${Curfreq} ($(sed "s/performance/\x1b\x5b1mperformance\x1b\x5b0m/" <<<"${AvailableGovernors}")${AvailableFrequencies})"
else
echo "${Governor}${Curfreq} (${AvailableGovernors}${AvailableFrequencies})"
fi
fi
else
echo "${SysFSNode##*/}: ${Governor}${Curfreq}"
fi
fi
done | sort -n
} # HandleGovernors
HandlePolicies() {
# report available sysfs policies that might affect performance behaviour. Stuff like
# pcie_aspm, gpu/core_availability_policy, gpu/power_policy or iopolicy. With RK3588
# this might look like this for example:
#
# Status of performance related policies found below /sys:
# /sys/devices/platform/fb000000.gpu/power_policy: [coarse_demand] always_on
# /sys/module/pcie_aspm/parameters/policy: default performance [powersave] powersupersave
# use colours and bold when outputting to a terminal
[ -z "${BOLD}" ] && CheckTerminal
# If script is sourced we need to read in relevant dmesg contents
[ -z "${DMESG}" ] && DMESG="$(dmesg | grep pcie)"
# process policies
SysFSPolicies="$(find /sys -name "*policy" 2>/dev/null | grep -E -v 'hotplug|cpufreq|thermal_zone|apparmor|hostap|/sys/kernel|/sys/devices/pci|mobile_lpm_|xmit_hash_|fr_policy|selinux')"
if [ "X${SysFSPolicies}" = "X" ]; then
# skip if no policies found
return
fi
echo "${SysFSPolicies}" | while read ; do
read Policy <"${REPLY}"
if [ "X${Policy}" != "X" ]; then
case "${REPLY}" in
*pcie_aspm*)
# PCIe's ASPM gets special treatment since values are standardized
# so we can use coloured output. We also need to check for 'pcie'
# occurences in kernel ring buffer since reporting ASPM settings on
# devices lacking PCIe capabilities is pointless
grep -q pcie <<<"${DMESG}"
PCIeInDmesg=$?
if [ -d /sys/bus/pci_express ] && [ ${PCIeInDmesg} -eq 0 ]; then
case ${Policy} in
*"[performance]"*)
echo -e "${REPLY}: ${LGREEN}${Policy}${NC}"
;;
*"[powersave]"*|*"[powersupersave]"*)
echo -e "${REPLY}: ${LRED}${Policy}${NC}"
;;
*)
echo -e "${REPLY}: ${Policy}"
;;
esac
fi
;;
*)
# report policy if there is more than one value possible, otherwise skip
grep -q ' ' <<<"${Policy}" && echo -e "${REPLY}: ${Policy}"
;;
esac
fi
done | sort -n
} # HandlePolicies
PlotPerformanceGraph() {
# function that walks through all cpufreq OPP and plots a performance graph using
# 7-ZIP MIPS. Needs gnuplot and htmldoc (Debian/Ubuntu: gnuplot-nox htmldoc packages)
local i
if [ ! -f /sys/devices/system/cpu/cpufreq/policy0/scaling_governor ]; then
# no cpufreq support -> no way to test through different clockspeeds. Stop
echo -e " Done.\nNo cpufreq support available. Not able to draw performance graph(s)."
exit 1
fi
# repeat every measurement at least this many times and do not measure any cpufreq below
MinRepetitions=3 # how many times should each measurement be repeated
Repetitions=$(( 1000000000 / ${QuickAndDirtyPerformance} ))
[ ${Repetitions} -lt ${MinRepetitions} ] && Repetitions=${MinRepetitions}
SkipBelow=${MinKHz:-600000} # minimum cpufreq in KHz to measure
if [ "X${OutputCurrents[*]}" != "X" ]; then
# We are in Netio monitoring mode, so measure idle consumption first,
# set all governors and PCIe ASPM to lowest clockspeed / powersave
HandleGovernors powersave
NetioConsumptionFile="${TempDir}/netio.current"
echo -n $(( $(awk '{printf ("%0.0f",$1/10); }' <<<"${OutputCurrent[$(( ${NetioSocket} - 1 ))]}" ) * 10 )) >"${NetioConsumptionFile}"
export NetioConsumptionFile
/bin/bash "${PathToMe}" -N "${NetioDevice}" "${NetioSocket}" "${NetioConsumptionFile}" "4.8" "30" >/dev/null 2>&1 &
NetioMonitoringPID=$!
echo -e "\x08\x08 Done.\nTrying to determine idle consumption...\c"
echo -e "System health while idling for 4 minutes:\n" >>"${MonitorLog}"
/bin/bash "${PathToMe}" -m 30 >>"${MonitorLog}" &
MonitoringPID=$!
snore 240
read IdleConsumption <"${NetioConsumptionFile}"
kill ${NetioMonitoringPID} ${MonitoringPID}
IdleTemp=$(ReadSoCTemp)
echo -e "\n##########################################################################\n\nIdle temperature: ${IdleTemp}°C, idle consumption: $(( $(awk '{printf ("%0.0f",$1/10); }' <<<"${IdleConsumption}" ) * 10 )) mW" >>"${ResultLog}"
fi
CheckNetio
# check if cpulist parameter has been provided as well:
if [ "X${CPUList}" = "X" ]; then
# -g has been used without further restrictions, we run performance test on all cores
CheckPerformance "all CPU cores" "$(tr -d '[:space:]' <<<"${ClusterConfig[@]}")"
PlotGraph "all CPU cores" "$(tr -d '[:space:]' <<<"${ClusterConfig[@]}")"
RenderPDF
else
# -g with additional options has been called
case ${CPUList} in
cores)
# check each core of every cluster, on RK3399 for example 0 and 4
for i in $(seq 0 $(( ${#ClusterConfig[@]} -1 )) ) ; do
FirstCore=${ClusterConfig[$i]}
CheckPerformance "CPU ${FirstCore}" "${FirstCore}" "${FirstCore}"
CPUInfo="$(GetCPUInfo ${FirstCore})"
PlotGraph "CPU ${FirstCore}${CPUInfo}" "${FirstCore}"
done
RenderPDF
;;
clusters)
# check all cores of every cluster, on RK3399 for example 0-3 and 4-5
for i in $(seq 0 $(( ${#ClusterConfig[@]} -1 )) ) ; do
FirstCore=${ClusterConfig[$i]}
LastCore=$(GetLastClusterCore $(( $i + 1 )))
CheckPerformance "CPU ${FirstCore}-${LastCore}" "${FirstCore}" "${FirstCore}-${LastCore}"
CPUInfo="$(GetCPUInfo ${FirstCore})"
PlotGraph "CPU ${FirstCore}-${LastCore}${CPUInfo}" "${FirstCore}"
done
RenderPDF
;;
coreclusters)
# check all identical cores of every cluster, on RK3588 for example 0-3 and 4-7
# though this SoC consists of 3 clusters: 0-3 (A55), 4-5 (A76) and 6-7 (A76)
for i in $(seq 0 $(( ${#ClusterConfigByCoreType[@]} -1 )) ) ; do
FirstCore=${ClusterConfigByCoreType[$i]}
LastCore=$(GetLastClusterCoreByType $(( $i + 1 )))
CheckPerformance "CPU ${FirstCore}-${LastCore}" "${FirstCore}" "${FirstCore}-${LastCore}"
CPUInfo="$(GetCPUInfo ${FirstCore})"
PlotGraph "CPU ${FirstCore}-${LastCore}${CPUInfo}" "${FirstCore}"