one-core-peak: Avoid reporting Unknown memory speed
[fio.git] / t / one-core-peak.sh
1 #!/bin/bash
2
3 args=$*
4 first_cores=""
5 taskset_cores=""
6 first_cores_count=0
7 nb_threads=4 #default from the benchmark
8
9 fatal() {
10   echo "$@"
11   exit 1
12 }
13
14 hint() {
15   echo "Warning: $*"
16 }
17
18 info() {
19   item=$1
20   shift
21   echo "${item}: $*"
22 }
23
24 check_root() {
25   [[ ${EUID} -eq 0 ]] || fatal "You should be root to run this tool"
26 }
27
28 check_binary() {
29   # Ensure the binaries are present and executable
30   for bin in "$@"; do
31     if [ ! -x ${bin} ]; then
32       which ${bin} >/dev/null
33       [ $? -eq 0 ] || fatal "${bin} doesn't exists or is not executable"
34     fi
35   done
36 }
37
38
39 detect_first_core() {
40   # Detect which logical cpus belongs to the first physical core
41   # If Hyperthreading is enabled, two cores are returned
42   cpus=$(lscpu  --all -pSOCKET,CORE,CPU |grep "0,0")
43   for cpu in ${cpus}; do
44     IFS=','
45     # shellcheck disable=SC2206
46     array=(${cpu})
47     if [ ${first_cores_count} -eq 0 ]; then
48       first_cores="${array[2]}"
49     else
50       first_cores="${first_cores} ${array[2]}"
51     fi
52
53     first_cores_count=$((first_cores_count + 1))
54     unset IFS
55   done
56   [ ${first_cores_count} -eq 0 ] && fatal "Cannot detect first core"
57   taskset_cores=$(echo "${first_cores}" | tr ' ' ',')
58 }
59
60 check_args() {
61   [ $1 -eq 0 ] && fatal "Missing drive(s) as argument"
62 }
63
64 check_drive_exists() {
65   # Ensure the block device exists
66   [ -b $1 ] || fatal "$1 is not a valid block device"
67 }
68
69 is_nvme() {
70   [[ ${*} == *"nvme"* ]]
71 }
72
73 check_poll_queue() {
74   # Print a warning if the nvme poll queues aren't enabled
75   is_nvme ${args} || return
76   poll_queue=$(cat /sys/module/nvme/parameters/poll_queues)
77   [ ${poll_queue} -eq 0 ] && hint "For better performance, you should enable nvme poll queues by setting nvme.poll_queues=32 on the kernel commande line"
78 }
79
80 block_dev_name() {
81   echo ${1#"/dev/"}
82 }
83
84 get_sys_block_dir() {
85   # Returns the /sys/block/ directory of a given block device
86   device_name=$1
87   sys_block_dir="/sys/block/${device_name}"
88   [ -d "${sys_block_dir}" ] || fatal "Cannot find ${sys_block_dir} directory"
89   echo ${sys_block_dir}
90 }
91
92 check_io_scheduler() {
93   # Ensure io_sched is set to none
94   device_name=$(block_dev_name $1)
95   sys_block_dir=$(get_sys_block_dir ${device_name})
96   sched_file="${sys_block_dir}/queue/scheduler"
97   [ -f "${sched_file}" ] || fatal "Cannot find IO scheduler for ${device_name}"
98   grep -q '\[none\]' ${sched_file}
99   if [ $? -ne 0 ]; then
100     info "${device_name}" "set none as io scheduler"
101     echo "none" > ${sched_file}
102   fi
103
104 }
105
106 check_sysblock_value() {
107   device_name=$(block_dev_name $1)
108   sys_block_dir=$(get_sys_block_dir ${device_name})
109   target_file="${sys_block_dir}/$2"
110   value=$3
111   [ -f "${target_file}" ] || fatal "Cannot find ${target_file} for ${device_name}"
112   content=$(cat ${target_file})
113   if [ "${content}" != "${value}" ]; then
114     info "${device_name}" "${target_file} set to ${value}."
115     echo ${value} > ${target_file} 2>/dev/null || hint "${device_name}: Cannot set ${value} on ${target_file}"
116   fi
117 }
118
119 compute_nb_threads() {
120   # Increase the number of threads if there is more devices or cores than the default value
121   [ $# -gt ${nb_threads} ] && nb_threads=$#
122   [ ${first_cores_count} -gt ${nb_threads} ] && nb_threads=${first_cores_count}
123 }
124
125 check_scaling_governor() {
126   driver=$(LC_ALL=C cpupower frequency-info |grep "driver:" |awk '{print $2}')
127   if [ -z "${driver}" ]; then
128     hint "Cannot detect processor scaling driver"
129     return
130   fi
131   cpupower frequency-set -g performance >/dev/null 2>&1 || fatal "Cannot set scaling processor governor"
132 }
133
134 check_idle_governor() {
135   filename="/sys/devices/system/cpu/cpuidle/current_governor"
136   if [ ! -f "${filename}" ]; then
137     hint "Cannot detect cpu idle governor"
138     return
139   fi
140   echo "menu" > ${filename} 2>/dev/null || fatal "Cannot set cpu idle governor to menu"
141 }
142
143 show_nvme() {
144   device_name=$(block_dev_name $1)
145   device_dir="/sys/block/${device_name}/device/"
146   pci_addr=$(cat ${device_dir}/address)
147   pci_dir="/sys/bus/pci/devices/${pci_addr}/"
148   link_speed=$(cat ${pci_dir}/current_link_speed)
149   irq=$(cat ${pci_dir}/irq)
150   numa=$(cat ${pci_dir}/numa_node)
151   cpus=$(cat ${pci_dir}/local_cpulist)
152   model=$(cat ${device_dir}/model | xargs) #xargs for trimming spaces
153   fw=$(cat ${device_dir}/firmware_rev | xargs) #xargs for trimming spaces
154   serial=$(cat ${device_dir}/serial | xargs) #xargs for trimming spaces
155   info ${device_name} "MODEL=${model} FW=${fw} serial=${serial} PCI=${pci_addr}@${link_speed} IRQ=${irq} NUMA=${numa} CPUS=${cpus} "
156 }
157
158 show_device() {
159   device_name=$(block_dev_name $1)
160   is_nvme $1 && show_nvme $1
161 }
162
163 show_system() {
164 CPU_MODEL=$(grep -m1 "model name" /proc/cpuinfo | awk '{print substr($0, index($0,$4))}')
165 KERNEL=$(uname -r)
166 info "system" "CPU: ${CPU_MODEL}"
167 info "system" "MEMORY: ${MEMORY_SPEED}"
168 info "system" "KERNEL: ${KERNEL}"
169 MEMORY_SPEED=$(dmidecode -t 17 -q | grep -m 1 "Configured Memory Speed: [0-9]" | awk '{print substr($0, index($0,$4))}')
170 }
171
172 ### MAIN
173 check_args $#
174 check_root
175 check_binary t/io_uring lscpu grep taskset cpupower awk tr xargs dmidecode
176 detect_first_core
177
178 info "##################################################"
179 show_system
180 for drive in ${args}; do
181   check_drive_exists ${drive}
182   check_io_scheduler ${drive}
183   check_sysblock_value ${drive} "queue/iostats" 0 # Ensure iostats are disabled
184   check_sysblock_value ${drive} "queue/nomerges" 2 # Ensure merge are disabled
185   check_sysblock_value ${drive} "queue/io_poll" 1 # Ensure io_poll is enabled
186   show_device ${drive}
187 done
188
189 check_poll_queue
190 compute_nb_threads ${args}
191 check_scaling_governor
192 check_idle_governor
193
194 info "##################################################"
195 echo
196
197 cmdline="taskset -c ${taskset_cores} t/io_uring -b512 -d128 -c32 -s32 -p1 -F1 -B1 -n${nb_threads} ${args}"
198 info "io_uring" "Running ${cmdline}"
199 ${cmdline}