Last active
August 12, 2022 19:41
-
-
Save kigster/8ddebf9fddff25620e64d558dd4d56b7 to your computer and use it in GitHub Desktop.
Detect if MRI Ruby is built with jemalloc library or not, download with `curl -fSL http://bit.ly/ruby-jemalloc-check > ruby-jemalloc-check.sh`
This file contains 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
#!/usr/bin/env bash | |
# vi: ft=sh | |
# | |
# https://gist.github.com/kigster/8ddebf9fddff25620e64d558dd4d56b7 | |
# | |
# © 2019-2022 Konstantin Gredeskoul, Inc., All rights reserved. | |
# MIT LICENSE | |
# ———————————————————————————————————————————————————————————————— | |
# This script verifies that the ruby interpreter (either the one in | |
# the $PATH, or the one specified by the -r / --ruby option) is linked | |
# with jemalloc library for efficient memory utilization. | |
# | |
# It works well on Linux and Mac OSX. | |
# | |
# BACKGROUND | |
# ———————————————————————————————————————————————————————————————— | |
# Ruby versions 2.5 and earlier had a simpler method, typically | |
# running the following command and expecting the output to | |
# contain something like '-ljemalloc -lm ... ' | |
# | |
# ruby -r rbconfig -e "puts RbConfig.CONFIG['LIBS']" | |
# | |
# Unfortunately, this method no longer works with Ruby 2.6 | |
# and later, nor did it ever work with Linux. | |
# | |
# For this reason, the following script is provided to verify | |
# if your Ruby is using jemalloc memory allocator or not. | |
# | |
# USAGE: | |
# curl -fSL http://bit.ly/ruby-jemalloc-check > ruby-jemalloc-check.sh | |
# chmod 755 ruby-jemalloc-check.sh | |
# | |
# ./ruby-jemalloc-check.sh --help | |
# ./ruby-jemalloc-check.sh -r /usr/bin/ruby | |
# | |
# ———————————————————————————————————————————————————————————————— | |
set +e | |
export jm_option_ruby=$(command -v ruby 2>/dev/null) | |
export jm_option_quiet=false | |
export jm_action_detect=false | |
export jm_action_stats=false | |
export jm_action_help=false | |
export color_red="\e[1;31m" | |
export color_green="\e[1;32m" | |
export color_yellow="\e[1;33m" | |
export color_blue="\e[1;34m" | |
export clr="\e[0m" | |
function jm.printf() { | |
if "${jm_option_quiet}"; then | |
echo >/dev/null | |
else | |
printf "$@" | |
fi | |
} | |
# @description prints the info about current version of ruby | |
function jm.ruby.report() { | |
jm.printf "${color_blue}Ruby version being tested:\n → ${color_yellow}${jm_option_ruby} ${color_blue}$(jm.ruby.describe)${clr}\n" | |
} | |
# @description Prints ruby version under test | |
function jm.ruby.describe() { | |
${jm_option_ruby} -e 'puts "#{RUBY_VERSION} (#{RUBY_PLATFORM})"' | |
${jm_option_ruby} -e 'puts "#{RUBY_VERSION} (#{RUBY_PLATFORM})"' | |
} | |
# @description detects jemalloc or exits | |
function js.jemalloc.detect-or-exit() { | |
jm.jemalloc.detect-quiet || { | |
jm.printf "${color_red}ERROR: No jemalloc detected in ruby ${jm_option_ruby}${clr}\n" | |
exit 1 | |
} | |
} | |
# @description prints jemalloc statistics if jemalloc is available | |
function jm.jemalloc.stats() { | |
js.jemalloc.detect-or-exit | |
MALLOC_CONF=stats_print:true ${jm_option_ruby} -e "exit" 2>&1 | less -S | |
} | |
# @description returns 0 if jemalloc was detected or 1 otherwise | |
function jm.jemalloc.detect-quiet() { | |
MALLOC_CONF=stats_print:true ${jm_option_ruby} -e "exit" 2>&1 | grep -q "jemalloc statistics" | |
} | |
# @description detects if jemalloc is linked and if so prints the info to output | |
function jm.jemalloc.detect-loud() { | |
jm.printf "${color_blue}Checking if ruby ${color_yellow}${jm_option_ruby}${color_blue} is linked with jemalloc... \n" | |
jm.printf "${color_yellow}$(jm.ruby.report)${clr}\n\n" | |
jm.jemalloc.detect-quiet | |
local code=$? | |
if [[ ${code} -eq 0 ]]; then | |
jm.printf " ✅ ${color_green} — jemalloc was detected.\n" | |
else | |
jm.printf " 🚫 ${color_red} — jemalloc was not detected.\n" | |
fi | |
jm.printf "${clr}\n" | |
return ${code} | |
} | |
# @description Prints the help screen and exits | |
function usage() { | |
jm.printf " | |
${color_green}USAGE:${clr} | |
${color_yellow}$(basename $0) [ options ]${clr} | |
${color_green}DESCRIPTION:${clr} | |
This script verifies that a given ruby binary is linked with jemalloc, | |
the optimized for defragmentation memory allocator, which is a drop-in | |
replacement for libc malloc. | |
The script has several actions: | |
- check if the ruby binary is linked with jemalloc (-j/--jemalloc) | |
- print jemalloc statistics if available (-s/--stats) | |
- print this help screen (-h/--help) | |
${color_green}ACTIONS:${clr} | |
-j/--jemalloc Check if the ruby binary is linked with jemalloc | |
-h/--help This page (also printed when no arguments are provided) | |
-s/--stats Print the jemalloc stats (when linked with jemalloc) | |
${color_green}OPTIONS:${clr} | |
-r/--ruby PATH Path to the ruby binary to check (defaults to the | |
first ruby found in the \$PATH) | |
-q/--quiet Do not print output, exit with 1 if no jemalloc, or 0 | |
if jemalloc was found. | |
" | |
exit 0 | |
} | |
if [[ -z $* ]]; then | |
usage | |
fi | |
# Parse additional flags | |
while :; do | |
case $1 in | |
-d | --detect) | |
shift | |
export jm_action_detect=true | |
;; | |
-s | --stats) | |
shift | |
export jm_action_stats=true | |
;; | |
-h | -\? | --help) | |
shift | |
export jm_action_help=true | |
;; | |
-q | --quiet) | |
shift | |
export jm_option_quiet=true | |
;; | |
-r | --ruby) | |
shift | |
if [[ -x $1 && $(basename $1) == "ruby" ]]; then | |
export jm_option_ruby="$1" | |
else | |
jm.printf "${color_red} Invalid ruby interpreter provided: $1${clr}\n" | |
exit 1 | |
fi | |
shift | |
;; | |
--) # End of all options; anything after will be passed to the action function | |
shift | |
break | |
;; | |
*) | |
[[ -n $1 ]] && { | |
jm.printf "${color_red}ERROR: invalid option: $1${clr}\n" | |
exit 1 | |
} | |
break | |
;; | |
esac | |
done | |
if ${jm_action_help}; then | |
usage | |
fi | |
jm.printf "${color_green}Using Ruby Binary: ${color_yelow}${jm_option_ruby}${clr}\n" | |
if ${jm_option_quiet}; then | |
jm.jemalloc.detect-quiet | |
exit $? | |
fi | |
if ${jm_action_detect}; then | |
jm.jemalloc.detect-loud | |
exit $? | |
fi | |
if ${jm_option_stats}; then | |
jm.jemalloc.stats | |
exit $? | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment