121 lines
3.8 KiB
Bash
121 lines
3.8 KiB
Bash
#!/bin/bash
|
|
|
|
# The qemu command details and the 98-102% range is taken from
|
|
# find-lapictscdeadline-optimal.sh and run-tscdeadline-latency.sh
|
|
# from the tuned package available at
|
|
# https://git.fedorahosted.org/cgit/tuned.git/tree/profiles/realtime-virtual-host
|
|
#
|
|
# The upstream code has no copyright notice in the scripts, but the
|
|
# overall package is licensed under the GPLv2
|
|
#
|
|
# Copyright(c) 2016-2017 Wind River Systems, Inc. All rights reserved.
|
|
|
|
QEMU=/usr/libexec/qemu-kvm
|
|
ADVANCE_FILE="/sys/module/kvm/parameters/lapic_timer_advance_ns"
|
|
ADVANCE_CALIB="/etc/nova/calibrated_lapic_timer_advance_ns"
|
|
ADVANCE_GOENABLED="/var/run/.nova_timer_advance_enabled"
|
|
|
|
function log ()
|
|
{
|
|
logger -p local1.info -t $0 $@
|
|
echo $0: "$@"
|
|
}
|
|
|
|
|
|
rm -f ${ADVANCE_GOENABLED}
|
|
|
|
if [ ! -f $ADVANCE_FILE ]; then
|
|
touch ${ADVANCE_GOENABLED}
|
|
exit 1
|
|
fi
|
|
|
|
# Use previous calibrated advance result
|
|
if [ -f $ADVANCE_CALIB ]; then
|
|
read -r advance < $ADVANCE_CALIB
|
|
if [[ "$advance" =~ ^[0-9]+$ ]]; then
|
|
echo $advance > $ADVANCE_FILE
|
|
log "using advance value of" $(cat $ADVANCE_FILE)
|
|
touch ${ADVANCE_GOENABLED}
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Move ourselves to the nova global cpuset. This will ensure that
|
|
# we run on a CPU that isn't being used by management or vswitch.
|
|
VCPU_PIN_STR=$(grep vcpu_pin_set /etc/nova/nova.conf)
|
|
VCPU_PIN_STR=${VCPU_PIN_STR//\"/}
|
|
FLOAT_CPUS=${VCPU_PIN_STR##*=}
|
|
if [ -z "${FLOAT_CPUS}" ]; then
|
|
log "skip calibration, we have not configured yet"
|
|
exit 0
|
|
fi
|
|
log "Calibrating with FLOAT_CPUS: ${FLOAT_CPUS}"
|
|
taskset --pid --cpu-list ${FLOAT_CPUS} $$ &> /dev/null
|
|
|
|
dir=$(mktemp -d)
|
|
|
|
advance=1500
|
|
latency=1000000
|
|
|
|
|
|
for i in $(seq 1500 500 7000); do
|
|
log "test advance ${i}"
|
|
echo $i > $ADVANCE_FILE
|
|
timeout --foreground --signal TERM 10s \
|
|
chrt -f 1 stdbuf -oL ${QEMU} -enable-kvm -device pc-testdev \
|
|
-device isa-debug-exit,iobase=0xf4,iosize=0x4 \
|
|
-display none -serial stdio -device pci-testdev \
|
|
-kernel /usr/share/qemu-kvm/tscdeadline_latency.flat \
|
|
-cpu host | awk 'NF==2 && /latency:/ {print $2}' > ${dir}/out0
|
|
# chomp last line since output may be incomplete
|
|
sed \$d < ${dir}/out0 > ${dir}/out
|
|
|
|
# Calculate the average of all the latency numbers output by
|
|
# the test image.
|
|
A=0
|
|
while read l; do
|
|
A=$(($A + $l))
|
|
done < $dir/out
|
|
|
|
lines=$(wc -l $dir/out | cut -f 1 -d " ")
|
|
if [ ${lines} -eq 0 ]; then
|
|
# this shouldn't happen
|
|
log "got no output from test, aborting"
|
|
break
|
|
fi
|
|
|
|
ans=$(($A/$lines))
|
|
|
|
# Get the current latency as a percentage of the previous latency
|
|
value=$((${ans}*100/${latency}))
|
|
|
|
if [ $value -ge 102 ]; then
|
|
# Latency has increased by too much, we don't want to use this
|
|
# much advance. I didn't see this in practice, this is just
|
|
# a sanity check.
|
|
advance=$((${i} - 500))
|
|
log "latency too large, reverting to advance of ${advance}"
|
|
echo $advance > $ADVANCE_FILE
|
|
break
|
|
elif [ $value -ge 98 ]; then
|
|
# If we're close to the previous latency, then use the current
|
|
# advance. The algorithm has a tendency to underestimate a bit,
|
|
# so we don't want to use the previous advance value.
|
|
break
|
|
else
|
|
# We're substantially lower than the previous latency, so store
|
|
# the current advance and latency numbers and loop through again
|
|
# to see if it improves further with a bit higher advance.
|
|
latency=$ans
|
|
advance=$i
|
|
fi
|
|
done
|
|
|
|
# Save calibrated result
|
|
cat $ADVANCE_FILE > $ADVANCE_CALIB
|
|
log "using advance value of" $(cat $ADVANCE_FILE)
|
|
|
|
rm -rf $dir
|
|
touch ${ADVANCE_GOENABLED}
|
|
exit 0
|