Compute percentage memory sizes with integer arithmetic (#4252)

Co-authored-by: LCB <me@lbellows.com>
This commit is contained in:
LB
2026-08-31 21:21:42 -05:00
committed by GitHub
co-authored by LCB
parent 430805da64
commit bbc31603e2
2 changed files with 39 additions and 16 deletions
+9 -5
View File
@@ -513,11 +513,15 @@ elif [[ ${TYPE} == "CURSEFORGE" ]]; then
if isPercentage "$INIT_MEMORY" || isPercentage "$MAX_MEMORY"; then if isPercentage "$INIT_MEMORY" || isPercentage "$MAX_MEMORY"; then
# Convert to bytes # Convert to bytes
NORM_INIT_MEM=$(normalizeMemSize "$INIT_MEMORY") if ! NORM_INIT_MEM=$(normalizeMemSize "$INIT_MEMORY"); then
NORM_MAX_MEM=$(normalizeMemSize "$MAX_MEMORY") exit 1
# Convert to MB fi
((NORM_INIT_MEM*=1048576)) if ! NORM_MAX_MEM=$(normalizeMemSize "$MAX_MEMORY"); then
((NORM_MAX_MEM*=1048576)) exit 1
fi
# Convert bytes to MB
((NORM_INIT_MEM/=1048576))
((NORM_MAX_MEM/=1048576))
cat > "${FTB_DIR}/settings-local.sh" <<EOF cat > "${FTB_DIR}/settings-local.sh" <<EOF
export MIN_RAM="${NORM_INIT_MEM}M" export MIN_RAM="${NORM_INIT_MEM}M"
+30 -11
View File
@@ -368,9 +368,22 @@ function logRcon() {
} }
function normalizeMemSize() { function normalizeMemSize() {
# Convert a JVM-style size (k/m/g) or a percentage of the container memory
# limit into bytes. Bash arithmetic is integer-only, so percentages cannot
# use a 0.01 scale factor.
local input=${1?}
local val=${input:0:-1}
local scale=1 local scale=1
local mem=1 local mem
case ${1,,} in
val=${val// /}
val=${val%%.*}
if ! [[ $val =~ ^[0-9]+$ ]]; then
logError "Unable to parse memory size '$input'"
return 1
fi
case ${input,,} in
*k) *k)
scale=1024 scale=1024
;; ;;
@@ -381,19 +394,25 @@ function normalizeMemSize() {
scale=1073741824 scale=1073741824
;; ;;
*%) *%)
# Get system memory if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then
if [ -f "/sys/fs/cgroup/memory/memory.limit_in_bytes" ]; then mem=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
mem=$( cat /sys/fs/cgroup/memory/memory.limit_in_bytes ) elif [ -f /sys/fs/cgroup/memory.max ]; then
elif [ -f "/sys/fs/cgroup/memory.max" ]; then mem=$(cat /sys/fs/cgroup/memory.max)
mem=$( cat /sys/fs/cgroup/memory.max )
fi fi
# Scale is used to transform percentages into decimals (eg. 60 -> 0.6) # cgroup v2 unlimited is "max"; cgroup v1 uses a large sentinel (~2^63).
scale=0.01 if [[ $mem == max || ! $mem =~ ^[0-9]+$ ]] || (( mem > 1 << 62 )); then
mem=$(awk '/MemTotal:/ { print $2 * 1024 }' /proc/meminfo)
fi
if ! [[ $mem =~ ^[0-9]+$ ]]; then
logError "Unable to determine memory limit for percentage value '$input'"
return 1
fi
echo $((val * mem / 100))
return 0
;; ;;
esac esac
val=${1:0:-1} echo $((val * scale))
echo $((val * scale * mem))
} }
function compare_version() { function compare_version() {