Files
ic-builder 1e6973a4b0
ci / audit (pull_request) Successful in 24s
fix SC2015 for CI shellcheck 0.9 (unambiguous if-forms)
CI red fix per the all-CI-green mandate; same pattern as the KNELCa/
KNELInventory fixes. No behavior change.
CI evidence: https://git.knownelement.com/KNEL/KNELPerf/actions
Ticket: https://projects.knownelement.com/issues/784
2026-09-06 14:29:45 -05:00

64 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# KNELPerf day/night resource profile engine.
#
# Broken out of ultix staged/ukrrs-daynight.sh (2026-09-06, #826) and
# redesigned: slice names, devices, and all numeric knobs are CONF-driven
# (no host-specific hardcoding); slice targets are a list so any host can
# run it. Runtime-only changes (set-property --runtime + sysctl + readahead):
# a reboot always lands safely in day mode, because slice unit files carry
# the day defaults (unchanged ultix invariant).
#
# Usage: knelperf-daynight.sh [--conf FILE] day|night
set -euo pipefail
CONF=${KNELPERF_DAYNIGHT_CONF:-/etc/knelperf/daynight.conf}
while [ $# -gt 0 ]; do
case "$1" in
--conf) CONF=$2; shift 2 ;;
day|night) MODE=$1; shift ;;
*) echo "usage: $0 [--conf FILE] day|night" >&2; exit 2 ;;
esac
done
[ "${MODE:-}" ] || { echo "usage: $0 [--conf FILE] day|night" >&2; exit 2; }
[ -r "$CONF" ] && . "$CONF"
# Targets: "slice:CPUWeight:AllowedCPUs:MemoryHigh" per mode, space-separated.
# Empty fields mean "skip that property". See knelperf-daynight.conf.example.
: "${DAY_SLICES:=}"; : "${NIGHT_SLICES:=}"
# Block devices for readahead tuning (space-separated; partitions auto-appended).
: "${BLOCK_DEVS:=}"
: "${DATA_RA_DAY:=256}"; : "${DATA_RA_NIGHT:=2048}"
: "${DIRTY_DAY:=1073741824}"; : "${DIRTY_NIGHT:=2147483648}"
: "${DIRTY_BG_DAY:=268435456}"; : "${DIRTY_BG_NIGHT:=536870912}"
log() { echo "[knelperf-daynight] $*"; }
ra=$DATA_RA_DAY; dirty=$DIRTY_DAY; dirtybg=$DIRTY_BG_DAY; slices=$DAY_SLICES
[ "$MODE" = night ] && { ra=$DATA_RA_NIGHT; dirty=$DIRTY_NIGHT; dirtybg=$DIRTY_BG_NIGHT; slices=$NIGHT_SLICES; }
apply_slice() { # "slice:weight:cpus:memhigh"
local spec=$1 slice weight cpus memhigh
IFS=: read -r slice weight cpus memhigh <<< "$spec"
[ -n "$slice" ] || return 0
local -a props=()
[ -n "$weight" ] && props+=(CPUWeight="$weight")
[ -n "$cpus" ] && props+=(AllowedCPUs="$cpus")
[ -n "$memhigh" ] && props+=(MemoryHigh="$memhigh")
if [ ${#props[@]} -gt 0 ]; then
systemctl set-property --runtime "$slice" "${props[@]}" \
|| log "WARN: set-property failed for $slice (slice not loaded?)"
fi
}
for spec in $slices; do apply_slice "$spec"; done
if [ -n "$BLOCK_DEVS" ]; then
for dev in $BLOCK_DEVS; do
blockdev --setra "$ra" "$dev" 2>/dev/null || log "readahead skip: $dev"
for part in "${dev}"[0-9]*; do
if [ -e "$part" ]; then blockdev --setra "$ra" "$part" 2>/dev/null || true; fi
done
done
fi
sysctl -q -w vm.dirty_bytes="$dirty" vm.dirty_background_bytes="$dirtybg"
log "profile $MODE applied $(date -Is)"