Skip to content

Instantly share code, notes, and snippets.

@craigloewen-msft
Created September 18, 2023 20:01
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save craigloewen-msft/496078591e0bbbfdec9f144c6b50a8cc to your computer and use it in GitHub Desktop.
Save craigloewen-msft/496078591e0bbbfdec9f144c6b50a8cc to your computer and use it in GitHub Desktop.
Auto memory reclaim shell script
#!/bin/bash
# Put under /etc/autoMemoryReclaim.sh
# set variables at the top
low_cpu_usage=50 # Note: We work with integer percentages (e.g., 50%)
idle_time=2 # Minutes
cached_memory_limit=1000 # MB
percent_memory_to_reclaim=5 # Percentage as an integer
wait_period=3
# function to check if user is idle
is_idle() {
loadavg=$(cat /proc/loadavg)
load1=$(echo "$loadavg" | awk '{print $1}')
load5=$(echo "$loadavg" | awk '{print $2}')
load15=$(echo "$loadavg" | awk '{print $3}')
if (( $(echo "$load15 < $low_cpu_usage" | bc -l) )) && (( $(echo "$load1 < $low_cpu_usage" | bc -l) )) && (( $(echo "$load5 < $low_cpu_usage" | bc -l) )); then
return 0
else
return 1
fi
}
# function to get cached memory
get_cached_memory() {
mem_info=$(free -m | grep "^Mem:" | awk '{print $6}')
echo "$mem_info"
}
# initialize state
state="waiting_to_be_idle"
idle_counter=0
while true; do
if [[ $state == "waiting_to_be_idle" ]]; then
if is_idle; then
((idle_counter++))
echo "User is idle for $idle_counter minutes"
if ((idle_counter >= idle_time)); then
state="reclaiming_memory"
echo "User has been idle for $idle_time minutes, now moving to reclaiming memory state"
fi
else
idle_counter=0
echo "User is not idle"
fi
elif [[ $state == "reclaiming_memory" ]]; then
if is_idle; then
mem_cached=$(get_cached_memory)
echo "Mem cached: $mem_cached ! and $cached_memory_limit"
if [[ "$mem_cached" -lt "$cached_memory_limit" ]]; then
state="waiting_to_be_idle"
echo "Cached memory limit of $cached_memory_limit MB reached, now moving back to waiting to be idle state"
else
mem_total=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo)
mem_to_reclaim=$((mem_total * percent_memory_to_reclaim / 100))
echo "Reclaiming $mem_to_reclaim MB of memory"
echo "${mem_to_reclaim}M" | sudo tee -a /sys/fs/cgroup/unified/memory.reclaim
sleep $wait_period
fi
else
state="waiting_to_be_idle"
echo "User is not idle, now moving back to waiting to be idle state"
fi
fi
# check every minute
sleep $wait_period
done
#!/bin/bash
# Used if you want to log your memory values over time to see the behaviour.
csv_file="output.csv"
# Create the CSV file if it doesn't exist
if [[ ! -f "$csv_file" ]]; then
echo "Seconds Since Starting,Used Memory (MB),Cached Memory (MB),Free Memory (MB),1 Min CPU,5 Min CPU,15 Min CPU,Total Memory Available (MB),Total Memory Used by vmmemwsl (MB)" > "$csv_file"
fi
# Define conversion constants
MB=$((1024 * 1024))
# Start time
start_time=$(date +%s)
while true; do
echo "Collecting system information..."
# Get system memory information in bytes
mem_info=$(free -b | grep "Mem:")
used_mem=$(echo "$mem_info" | awk '{print $3}')
cached_mem=$(echo "$mem_info" | awk '{print $6}')
free_mem=$(echo "$mem_info" | awk '{print $4}')
# Convert memory values to megabytes
used_mem_mb=$((used_mem / MB))
cached_mem_mb=$((cached_mem / MB))
free_mem_mb=$((free_mem / MB))
# Get CPU load averages
load_1min=$(cat /proc/loadavg | awk '{print $1}')
load_5min=$(cat /proc/loadavg | awk '{print $2}')
load_15min=$(cat /proc/loadavg | awk '{print $3}')
# Get total memory available in Windows
echo "Fetching total memory available in Windows..."
total_mem_avail=$(powershell.exe "(Get-CimInstance -ClassName Win32_OperatingSystem).FreePhysicalMemory" | sed 's/\r$//')
# Convert total memory available to megabytes
total_mem_avail_mb=$((total_mem_avail / 1024))
# Get total memory used by vmmemwsl process
echo "Fetching total memory used by vmmemwsl process..."
total_mem_vmmem=$(powershell.exe "(Get-Process -Name vmmemwsl | Measure-Object -Property WS -Sum).Sum" | sed 's/\r$//')
# Convert total memory used by vmmemwsl to megabytes
total_mem_vmmem_mb=$((total_mem_vmmem / MB))
# Calculate seconds since starting
current_time=$(date +%s)
seconds_since_start=$((current_time - start_time))
# Append the values to the CSV file
echo "Appending system information to $csv_file..."
echo "$seconds_since_start,$used_mem_mb,$cached_mem_mb,$free_mem_mb,$load_1min,$load_5min,$load_15min,$total_mem_avail_mb,$total_mem_vmmem_mb" >> "$csv_file"
echo "System information collected and logged successfully."
# Wait for 1 second before the next iteration
echo "Waiting for the next iteration..."
sleep 10
done
# Make sure your /etc/wsl.conf file looks like this to have the script auto start on start up of your WSL distro
[boot]
command=/etc/autoMemoryReclaim.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment