Commit 330e9f77 authored by Michal Berger's avatar Michal Berger Committed by Tomasz Zawadzki
Browse files

test/scheduler: Commonize collect_cpu_idle()



Signed-off-by: default avatarMichal Berger <michalx.berger@intel.com>
Signed-off-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I72da312e0d7fe71ae40b582501b52be615de4b63
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7564


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 0ea89560
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -483,3 +483,35 @@ get_cpu_time() {

	xtrace_restore
}

collect_cpu_idle() {
	((${#cpus_to_collect[@]} > 0)) || return 1

	local time=${1:-5}
	local cpu
	local samples
	local -g is_idle=()

	printf 'Collecting cpu idle stats (cpus: %s) for %u seconds...\n' \
		"${cpus_to_collect[*]}" "$time"

	get_cpu_time "$time" idle "${cpus_to_collect[@]}"

	for cpu in "${cpus_to_collect[@]}"; do
		samples=(${cpu_times[cpu]})
		printf '* cpu%u idle samples: %s (avg: %u%%)\n' \
			"$cpu" "${samples[*]}" "${avg_cpu_time[cpu]}"
		# Cores with polling reactors have 0% idle time,
		# while the ones in interrupt mode won't have 100% idle.
		# Work can be potentially be scheduled to the core by kernel,
		# to prevent that affecting tests set reasonably high idle limit.
		# Consider last sample
		if ((samples[-1] >= 70)); then
			printf '* cpu%u is idle\n' "$cpu"
			is_idle[cpu]=1
		else
			printf '*cpu%u is not idle\n' "$cpu"
			is_idle[cpu]=0
		fi
	done
}
+0 −56
Original line number Diff line number Diff line
@@ -15,62 +15,6 @@ fold_list_onto_array cpus $(parse_cpu_list <(echo "$spdk_cpus_csv"))
# Normalize the indexes
cpus=("${cpus[@]}")

collect_cpu_stat() {
	local list=$1
	local stat=$2

	for cpu in "${cpus_to_collect[@]}"; do
		eval "${list}[cpu]=\$(get_cpu_stat $cpu $stat)"
	done
}

collect_cpu_idle() {
	xtrace_disable

	local sample_time=${1:-5} samples=0
	local cpu bool inc user_hz

	# idle scales to USER_HZ so we use that in order to determine the expected
	# value it should have been increased to (more or less).
	user_hz=100
	# Expected increase of the idle stat
	inc=$((user_hz * sample_time))

	bool[0]="not" bool[1]="is"

	init_idle_samples=() idle_samples=() is_idle=()

	collect_cpu_stat init_idle_samples idle

	printf 'Collecting cpu idle stats (cpus: %s) for %u seconds...\n' \
		"${cpus_to_collect[*]}" "$sample_time"

	while ((++samples <= sample_time)) && sleep 1s; do
		collect_cpu_stat idle_samples idle
	done

	for cpu in "${!idle_samples[@]}"; do
		# We start to collect after the spdk app is initialized hence if the interrupt
		# mode is not working as expected, the idle time of given cpu will not have a
		# chance to increase. If it does work correctly, then it should change even for
		# a fraction, depending on how much time we spent on collecting this data.
		# If idle time is over 70% of expected increase then we consider this cpu as
		# idle. This is done in order to take into consideration time window the app
		# needs to actually spin up|down the cpu. It's also taken for granted that
		# there is no extra load on the target cpus which may be coming from other
		# processes.
		if ((idle_samples[cpu] > init_idle_samples[cpu] + (inc * 70 / 100))); then
			is_idle[cpu]=1
		else
			is_idle[cpu]=0
		fi
		printf 'cpu%u %s idle (%u %u)\n' \
			"$cpu" "${bool[is_idle[cpu]]}" "${init_idle_samples[cpu]}" "${idle_samples[cpu]}"
	done

	xtrace_restore
}

interrupt() {
	local busy_cpus
	local cpu thread