#!/usr/bin/env bash ## detect-memory-litespeed.sh — sibling to detect-memory.sh. ## Computes LSAPI_CHILDREN + extprocessor memSoftLimit/memHardLimit from ## container memory cap. Sourced by entrypoint-litespeed.sh. ## ---- container memory detection (mirrors detect-memory.sh) ---- CONTAINER_MEMORY_BYTES="" if [ -f /sys/fs/cgroup/memory.max ]; then val=$(cat /sys/fs/cgroup/memory.max 2>/dev/null) if [ "$val" != "max" ] && [ -n "$val" ]; then CONTAINER_MEMORY_BYTES=$val fi fi if [ -z "$CONTAINER_MEMORY_BYTES" ] && [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then val=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null) if [ -n "$val" ] && [ "$val" -lt 8589934592000 ] 2>/dev/null; then CONTAINER_MEMORY_BYTES=$val fi fi if [ -z "$CONTAINER_MEMORY_BYTES" ] && [ -f /proc/meminfo ]; then mem_kb=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo) if [ -n "$mem_kb" ]; then CONTAINER_MEMORY_BYTES=$((mem_kb * 1024)) fi fi if [ -z "$CONTAINER_MEMORY_BYTES" ]; then CONTAINER_MEMORY_BYTES=$((512 * 1024 * 1024)) fi CONTAINER_MEMORY_MB=$((CONTAINER_MEMORY_BYTES / 1024 / 1024)) ## ---- budget split (LSAPI workers get the lion's share) ---- OS_RESERVE_MB=50 OLS_RESERVE_MB=40 # OpenLiteSpeed daemon footprint DEV_OVERHEAD_MB=0 if [ "${environment:-PROD}" = "DEV" ]; then DEV_OVERHEAD_MB=125 fi AVAILABLE_MB=$((CONTAINER_MEMORY_MB - OS_RESERVE_MB - OLS_RESERVE_MB - DEV_OVERHEAD_MB)) if [ "$AVAILABLE_MB" -lt 60 ]; then AVAILABLE_MB=60 fi ## ---- LSAPI children (analogous to PHP_FPM_MAX_CHILDREN) ---- ## Per the 2026-06-02 cac-litespeed memory-sizing finding (vantagehealth ## OOM-spawn loop at 512 MB cap): each lsphp worker carries ~115 MB ## shmem-rss + ~25 MB anon + ~10 MB file ≈ 130-150 MB real cgroup cost ## per worker on heavy WP workloads. shmem is RSS-accounted per worker ## (vs cac-fpm's COW-shared fork model) so the cost is real per cgroup, ## not just per process. ## ## 115 (the previous default) was set from idle-state measurements and ## ran brain-jar.com into 142 OOM-kills at 1 GiB on 2026-06-02 night — ## the formula computed CHILDREN=8, which left zero headroom once Divi ## page renders started growing worker anon. Bumped to 130 to track the ## active per-worker cost; gives slightly fewer workers but real headroom. ## ## Sub-512 MB containers remain unsafe for dynamic WP on OLS — the floor ## of 2 workers still applies but it'll be cap-marginal. Per-site override ## via FPM_MAX_CHILDREN env var (panel edit-site UI) overrides this for ## sites where the default isn't right for their workload. LSPHP_WORKER_ESTIMATE_MB=${LSPHP_WORKER_ESTIMATE_MB:-130} calc_lsapi_children=$((AVAILABLE_MB / LSPHP_WORKER_ESTIMATE_MB)) if [ "$calc_lsapi_children" -lt 2 ]; then calc_lsapi_children=2 fi if [ "$calc_lsapi_children" -gt 50 ]; then calc_lsapi_children=50 fi ## Per-site override knobs — site-pool-env.php still passes FPM_MAX_CHILDREN ## for backward compat, so prefer LSAPI_CHILDREN if set, else FPM_MAX_CHILDREN, ## else the calculated value. LSAPI_CHILDREN=${LSAPI_CHILDREN:-${FPM_MAX_CHILDREN:-$calc_lsapi_children}} ## Per-worker mem limits (RLIMIT_AS) live in httpd_config.tpl now as ## hard-coded 1024M soft / 1500M hard — those values comfortably fit ## typical Divi/WooCommerce VSZ (~280-365 MB) while still catching a ## true runaway script. Cgroup remains the real backstop. The earlier ## AVAILABLE/CHILDREN formula was killing legitimate workers because ## it conflated VSZ (RLIMIT_AS) with RSS-budget arithmetic. export CONTAINER_MEMORY_MB LSAPI_CHILDREN