Last active
August 28, 2024 08:58
-
-
Save corporatepiyush/318c0c6970caee8af36360a8f5e2df4c to your computer and use it in GitHub Desktop.
Memory optimisations using jemalloc and tcmalloc on Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# File: /usr/local/bin/configure_malloc.sh | |
set_malloc_config() { | |
local total_ram=$1 | |
local arena_max mmap_threshold trim_threshold top_pad | |
mmap_threshold=524288 # 512 KB | |
trim_threshold=524288 # 512 KB | |
if [ "$total_ram" -lt 8192 ]; then | |
arena_max=8 | |
top_pad=32768 # 32 KB | |
elif [ "$total_ram" -lt 32768 ]; then | |
arena_max=16 | |
top_pad=65536 # 64 KB | |
elif [ "$total_ram" -lt 65536 ]; then | |
arena_max=24 | |
top_pad=131072 # 128 KB | |
else | |
arena_max=32 | |
top_pad=524288 # 512 KB | |
fi | |
echo "$arena_max:$mmap_threshold:$trim_threshold:$top_pad" | |
} | |
update_environment_file() { | |
local env_file="/etc/environment" | |
local arena_max=$1 | |
local mmap_threshold=$2 | |
local trim_threshold=$3 | |
local top_pad=$4 | |
# Remove existing MALLOC and GLIBC_TUNABLES entries | |
sudo sed -i '/^MALLOC_/d' "$env_file" | |
sudo sed -i '/^GLIBC_TUNABLES/d' "$env_file" | |
# Append new entries | |
sudo tee -a "$env_file" > /dev/null << EOF | |
GLIBC_TUNABLES="glibc.malloc.arena_max=$arena_max:glibc.malloc.mmap_threshold=$mmap_threshold:glibc.malloc.trim_threshold=$trim_threshold:glibc.malloc.top_pad=$top_pad" | |
MALLOC_ARENA_MAX=$arena_max | |
MALLOC_MMAP_THRESHOLD_=$mmap_threshold | |
MALLOC_TRIM_THRESHOLD_=$trim_threshold | |
MALLOC_TOP_PAD_=$top_pad | |
MALLOC_MMAP_MAX_=2097152 | |
MALLOC_CHECK_=0 | |
MALLOC_PERTURB_=0 | |
EOF | |
echo "Memory allocator configuration updated in $env_file" | |
} | |
# Get total RAM size in MB | |
total_ram=$(free -m | awk '/^Mem:/{print $2}') | |
# Get malloc configuration based on total RAM | |
IFS=':' read -r arena_max mmap_threshold trim_threshold top_pad <<< "$(set_malloc_config "$total_ram")" | |
# Update /etc/environment with new configuration | |
update_environment_file "$arena_max" "$mmap_threshold" "$trim_threshold" "$top_pad" | |
echo "Configuration complete. Changes will take effect after reboot or re-login." | |
echo "To apply changes to the current session, run: source /etc/environment" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
grep -z 'LD_PRELOAD' /proc/<pid>/environ | tr '\0' '\n' | |
# if jemalloc is listed among the loaded libraries for a process. | |
lsof -p <pid> | grep jemalloc | |
# to list the shared libraries used by an executable | |
ldd /path/to/your/application | grep jemalloc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create a systemd override directory for MySQL | |
sudo mkdir -p /etc/systemd/system/mysql.service.d | |
# Create a systemd override file for MySQL | |
echo -e "[Service]\nEnvironment=\"LD_PRELOAD=/usr/local/lib/libjemalloc.so\"\nEnvironment=\"MALLOC_CONF='dirty_decay_ms:1000,narenas:2,background_thread:true'\"" | sudo tee /etc/systemd/system/mysqld.service.d/override.conf | |
# Reload systemd and restart MySQL | |
sudo systemctl daemon-reload | |
sudo systemctl restart mysql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Set jemalloc as the default allocator and MALLOC_ARENA_MAX=2 at the OS level | |
echo 'export LD_PRELOAD=/usr/local/lib/libjemalloc.so' | sudo tee -a /etc/profile.d/jemalloc.sh | |
echo "export MALLOC_CONF='dirty_decay_ms:1000,narenas:2,background_thread:true'" | sudo tee -a /etc/profile.d/jemalloc.sh | |
# Make the script executable | |
sudo chmod +x /etc/profile.d/jemalloc.sh | |
# Apply the environment variables immediately | |
source /etc/profile.d/jemalloc.sh |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create a systemd override directory for PostgreSQL | |
sudo mkdir -p /etc/systemd/system/postgresql.service.d | |
# Create a systemd override file for PostgreSQL | |
echo -e "[Service]\nEnvironment=\"LD_PRELOAD=/usr/local/lib/libjemalloc.so\"\nEnvironment=\"MALLOC_CONF='dirty_decay_ms:1000,narenas:2,background_thread:true'\"" | sudo tee /etc/systemd/system/postgresql.service.d/override.conf | |
# Reload systemd and restart PostgreSQL | |
sudo systemctl daemon-reload | |
sudo systemctl restart postgresql |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Add LD_PRELOAD to .bashrc | |
echo 'export LD_PRELOAD=/usr/local/lib/libjemalloc.so' >> ~/.bashrc | |
echo "export MALLOC_CONF='dirty_decay_ms:1000,narenas:2,background_thread:true'" >> ~/.bashrc | |
# Reload .bashrc to apply changes | |
source ~/.bashrc | |
# Add LD_PRELOAD to .bashrc | |
echo 'export LD_PRELOAD=/usr/local/lib/libjemalloc.so' >> ~/.zshrc | |
echo "export MALLOC_CONF='dirty_decay_ms:1000,narenas:2,background_thread:true'" >> ~/.zshrc | |
# Reload .zshrc to apply changes | |
source ~/.zshrc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Update package lists | |
sudo apt-get update | |
sudo apt-get upgrade | |
# Install dependencies | |
sudo apt-get install -y autoconf automake libtool make gcc | |
# Download jemalloc source code | |
JEMALLOC_VERSION=5.3.0 | |
wget https://github.com/jemalloc/jemalloc/releases/download/${JEMALLOC_VERSION}/jemalloc-${JEMALLOC_VERSION}.tar.bz2 | |
# Extract the downloaded tarball | |
tar -xvf jemalloc-${JEMALLOC_VERSION}.tar.bz2 | |
# Change to the extracted directory | |
cd jemalloc-${JEMALLOC_VERSION} | |
# Compile and install jemalloc | |
./autogen.sh | |
make | |
sudo make install |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e # Exit immediately if a command exits with a non-zero status | |
set -u # Treat unset variables as an error | |
# Function to log messages | |
log() { | |
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | |
} | |
# Function to handle errors | |
error_exit() { | |
log "ERROR: $1" >&2 | |
exit 1 | |
} | |
# Function to check if a command exists | |
command_exists() { | |
command -v "$1" >/dev/null 2>&1 | |
} | |
# Function to install TCMalloc | |
install_tcmalloc() { | |
log "Installing TCMalloc..." | |
if ! command_exists apt-get; then | |
error_exit "apt-get not found. This script requires a Debian-based system." | |
fi | |
sudo apt-get update || error_exit "Failed to update package list" | |
sudo apt-get install -y google-perftools || error_exit "Failed to install google-perftools" | |
} | |
# Function to find TCMalloc library | |
find_tcmalloc_lib() { | |
log "Finding TCMalloc library..." | |
TCMALLOC_LIB=$(ldconfig -p | grep libtcmalloc.so | awk '{print $4}' | head -n 1) | |
if [ -z "$TCMALLOC_LIB" ]; then | |
error_exit "libtcmalloc.so not found. Please check your installation." | |
fi | |
log "Found TCMalloc library at: $TCMALLOC_LIB" | |
} | |
# Function to set TCMalloc parameters based on RAM | |
set_tcmalloc_params() { | |
log "Setting TCMalloc parameters..." | |
total_ram_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}') | |
total_ram_gb=$((total_ram_kb / 1024 / 1024)) | |
# Default values | |
aggressive_decommit=false | |
release_rate=0.1 | |
large_alloc_threshold=4294967296 | |
# RAM-based configuration | |
if [ $total_ram_gb -le 8 ]; then | |
max_total_thread_cache_bytes=268435456 # 256 MB | |
transfer_batch_size=128 | |
elif [ $total_ram_gb -le 16 ]; then | |
max_total_thread_cache_bytes=536870912 # 512 MB | |
transfer_batch_size=256 | |
elif [ $total_ram_gb -le 32 ]; then | |
max_total_thread_cache_bytes=1073741824 # 1 GB | |
transfer_batch_size=512 | |
else | |
max_total_thread_cache_bytes=4294967296 # 4 GB | |
transfer_batch_size=1024 | |
fi | |
log "TCMalloc parameters set based on ${total_ram_gb}GB RAM" | |
} | |
# Function to update shell configuration files | |
update_shell_config() { | |
local config_file="$1" | |
log "Updating $config_file with TCMalloc settings..." | |
# Check if the config file exists | |
if [ ! -f "$config_file" ]; then | |
touch "$config_file" | |
fi | |
# Remove any existing TCMalloc configuration | |
sed -i '/# TCMalloc configuration/,/# End TCMalloc configuration/d' "$config_file" | |
# Append new TCMalloc configuration | |
cat << EOF >> "$config_file" | |
# TCMalloc configuration | |
export LD_PRELOAD='$TCMALLOC_LIB' | |
export TCMALLOC_LARGE_ALLOC_REPORT_THRESHOLD=$large_alloc_threshold | |
export TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES=$max_total_thread_cache_bytes | |
export TCMALLOC_AGGRESSIVE_DECOMMIT=$aggressive_decommit | |
export TCMALLOC_TRANSFER_BATCH_SIZE=$transfer_batch_size | |
export TCMALLOC_RELEASE_RATE=$release_rate | |
# End TCMalloc configuration | |
EOF | |
log "$config_file updated successfully." | |
} | |
# Function to update all relevant shell configuration files | |
update_shell_configs() { | |
update_shell_config "$HOME/.bashrc" | |
if command_exists zsh; then | |
update_shell_config "$HOME/.zshrc" | |
fi | |
} | |
# Function to verify the configuration | |
verify_configuration() { | |
log "Verifying TCMalloc configuration..." | |
if [ -z "${LD_PRELOAD:-}" ]; then | |
log "WARNING: LD_PRELOAD is not set in the current session." | |
log "Please run 'source ~/.bashrc' (for Bash) or 'source ~/.zshrc' (for Zsh)" | |
log "or start a new terminal session to apply the changes." | |
else | |
log "LD_PRELOAD is set to: $LD_PRELOAD" | |
fi | |
} | |
# Main execution | |
main() { | |
log "Starting TCMalloc configuration script..." | |
install_tcmalloc | |
find_tcmalloc_lib | |
set_tcmalloc_params | |
update_shell_configs | |
verify_configuration | |
log "TCMalloc configuration completed successfully." | |
log "To apply changes immediately, run: source ~/.bashrc (for Bash) or source ~/.zshrc (for Zsh)" | |
} | |
# Run the main function | |
main |
very helpful script
To make sure you are using the correct path for your jemalloc lib file one can use
find /usr -name "libjemalloc.so*"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sudo reboot
also helpful