CrackedRuby logo

CrackedRuby

YJIT New Configuration Options

Overview

Ruby provides multiple configuration mechanisms that control interpreter execution, runtime behavior, and application settings. The configuration system operates through command-line options, environment variables, global variables, and runtime modification of interpreter state.

The primary configuration interfaces include command-line arguments passed to the ruby executable, environment variables read during startup, and global variables that modify interpreter behavior during execution. Ruby processes these configurations in a specific precedence order, with command-line options typically overriding environment variables.

# Global configuration variables
$VERBOSE = true
$DEBUG = false
$LOAD_PATH << '/custom/library/path'

Ruby's configuration affects multiple subsystems including the garbage collector, memory allocation, thread scheduling, and I/O buffering. The interpreter reads configuration values during startup and applies them to internal data structures that control runtime behavior.

# Environment-based configuration
ENV['RUBY_GC_HEAP_INIT_SLOTS'] = '40000'
ENV['RUBY_THREAD_MACHINE_STACK_SIZE'] = '262144'

# Runtime configuration access
puts "Current encoding: #{Encoding.default_external}"
puts "Load path entries: #{$LOAD_PATH.size}"

Configuration options span performance tuning, debugging controls, library loading behavior, and output formatting. The system distinguishes between static options that require interpreter restart and dynamic options modifiable during execution.

Basic Usage

Command-line options modify Ruby's execution behavior when starting the interpreter. The most common options control debugging, warnings, and library loading.

# Enable verbose warnings and debug mode
# ruby -w -d script.rb

$VERBOSE = true  # Equivalent to -w flag
$DEBUG = true    # Equivalent to -d flag

puts "Warning level: #{$VERBOSE}"
puts "Debug mode: #{$DEBUG}"

Environment variables configure Ruby before the interpreter starts. These settings affect memory allocation, garbage collection, and threading behavior.

# Set garbage collector parameters
ENV['RUBY_GC_HEAP_INIT_SLOTS'] = '40000'
ENV['RUBY_GC_HEAP_FREE_SLOTS'] = '4000' 
ENV['RUBY_GC_HEAP_GROWTH_FACTOR'] = '1.8'

# Configure threading
ENV['RUBY_THREAD_MACHINE_STACK_SIZE'] = '131072'
ENV['RUBY_THREAD_VM_STACK_SIZE'] = '131072'

# Check current configuration
puts "GC heap slots: #{GC.stat[:heap_available_slots]}"
puts "Thread stack size: #{ENV['RUBY_THREAD_MACHINE_STACK_SIZE']}"

Load path configuration controls where Ruby searches for required files. The $LOAD_PATH global variable contains directories searched when loading libraries.

# Add custom library directories
$LOAD_PATH.unshift('/usr/local/lib/ruby/custom')
$LOAD_PATH << File.expand_path('../lib', __FILE__)

# Check load path
puts "Load path contains #{$LOAD_PATH.size} directories"
$LOAD_PATH.each_with_index do |path, index|
  puts "#{index}: #{path}"
end

# Require with custom load path
require 'custom_library'  # Searches $LOAD_PATH directories

Encoding configuration determines how Ruby handles text data. Default encodings affect string operations, file I/O, and regular expression matching.

# Set default encodings
Encoding.default_external = 'UTF-8'
Encoding.default_internal = 'UTF-8'

# Configure via environment variables
ENV['RUBY_EXTERNAL_ENCODING'] = 'UTF-8'
ENV['RUBY_INTERNAL_ENCODING'] = 'UTF-8'

# Verify encoding settings
puts "External encoding: #{Encoding.default_external}"
puts "Internal encoding: #{Encoding.default_internal}"
puts "Locale encoding: #{Encoding.locale_charmap}"

Error Handling & Debugging

Configuration errors typically manifest as startup failures, unexpected runtime behavior, or performance degradation. Ruby provides diagnostic tools for identifying configuration issues.

Invalid environment variable values cause Ruby to emit warnings or revert to default settings. The interpreter validates numeric environment variables and ignores malformed values.

# Invalid GC configuration handling
ENV['RUBY_GC_HEAP_INIT_SLOTS'] = 'invalid_number'

begin
  # Ruby ignores invalid values and uses defaults
  GC.start
  puts "GC heap slots: #{GC.stat[:heap_available_slots]}"
rescue => error
  puts "Configuration error: #{error.message}"
end

# Check for configuration warnings
previous_verbose = $VERBOSE
$VERBOSE = true

# This generates warnings for invalid configurations
ENV['RUBY_GC_HEAP_GROWTH_FACTOR'] = '-1.0'  # Invalid negative value

$VERBOSE = previous_verbose

Load path conflicts occur when multiple versions of the same library exist in different directories. Ruby loads the first matching file found in $LOAD_PATH order.

# Debugging load path issues
def debug_require(library_name)
  original_verbose = $VERBOSE
  $VERBOSE = true
  
  puts "Attempting to require: #{library_name}"
  puts "Load path search order:"
  
  $LOAD_PATH.each_with_index do |path, index|
    full_path = File.join(path, "#{library_name}.rb")
    exists = File.exist?(full_path)
    puts "  #{index}: #{path} [#{exists ? 'EXISTS' : 'missing'}]"
    
    if exists
      puts "  --> Would load: #{full_path}"
      break
    end
  end
  
  require library_name
rescue LoadError => error
  puts "Load error: #{error.message}"
  puts "Searched paths:"
  error.backtrace_locations&.first(5)&.each do |location|
    puts "  #{location}"
  end
ensure
  $VERBOSE = original_verbose
end

debug_require('json')

Encoding configuration errors produce garbled text output or encoding conversion exceptions. Ruby validates encoding names and falls back to system defaults for invalid values.

# Handle encoding configuration errors
def configure_encoding(external, internal = nil)
  begin
    external_encoding = Encoding.find(external)
    internal_encoding = internal ? Encoding.find(internal) : nil
    
    puts "Setting external encoding: #{external_encoding.name}"
    Encoding.default_external = external_encoding
    
    if internal_encoding
      puts "Setting internal encoding: #{internal_encoding.name}"
      Encoding.default_internal = internal_encoding
    end
    
  rescue ArgumentError => error
    puts "Encoding error: #{error.message}"
    puts "Available encodings: #{Encoding.list.first(10).map(&:name).join(', ')}"
    
    # Fall back to UTF-8
    Encoding.default_external = Encoding::UTF_8
    puts "Reverted to UTF-8 encoding"
  end
end

# Test with invalid encoding
configure_encoding('INVALID-ENCODING')
configure_encoding('UTF-8', 'ASCII')

Production Patterns

Production Ruby applications require careful configuration management for performance, monitoring, and deployment consistency. Configuration should be externalized and validated during application startup.

Environment-based configuration allows different settings across development, staging, and production environments without code changes. Applications typically validate required configuration values during initialization.

class ApplicationConfig
  REQUIRED_ENV_VARS = %w[
    RUBY_GC_HEAP_INIT_SLOTS
    RUBY_GC_HEAP_GROWTH_FACTOR
    DATABASE_URL
    REDIS_URL
  ].freeze
  
  def self.validate!
    missing_vars = REQUIRED_ENV_VARS.select { |var| ENV[var].nil? }
    
    unless missing_vars.empty?
      raise "Missing required environment variables: #{missing_vars.join(', ')}"
    end
    
    validate_numeric_configs
    validate_gc_settings
  end
  
  def self.validate_numeric_configs
    numeric_configs = {
      'RUBY_GC_HEAP_INIT_SLOTS' => 1000..100000,
      'RUBY_GC_HEAP_GROWTH_FACTOR' => 1.1..3.0,
      'RUBY_THREAD_MACHINE_STACK_SIZE' => 32768..1048576
    }
    
    numeric_configs.each do |var, range|
      value = ENV[var]&.to_f
      next unless value
      
      unless range.cover?(value)
        raise "#{var}=#{value} outside valid range #{range}"
      end
    end
  end
  
  def self.validate_gc_settings
    init_slots = ENV['RUBY_GC_HEAP_INIT_SLOTS']&.to_i
    growth_factor = ENV['RUBY_GC_HEAP_GROWTH_FACTOR']&.to_f
    
    if init_slots && growth_factor
      max_heap_size = init_slots * (growth_factor ** 10)
      if max_heap_size > 1_000_000
        warn "GC configuration may cause excessive memory usage: #{max_heap_size} slots"
      end
    end
  end
end

# Application startup
ApplicationConfig.validate!

Garbage collector tuning significantly impacts production performance. Applications should profile GC behavior under realistic load and adjust parameters accordingly.

class GCProfiler
  def self.configure_for_production
    # Conservative settings for web applications
    ENV['RUBY_GC_HEAP_INIT_SLOTS'] = '40000'
    ENV['RUBY_GC_HEAP_FREE_SLOTS'] = '4000'
    ENV['RUBY_GC_HEAP_GROWTH_FACTOR'] = '1.8'
    ENV['RUBY_GC_HEAP_GROWTH_MAX_SLOTS'] = '80000'
    ENV['RUBY_GC_OLDMALLOC_LIMIT'] = '16777216'
    ENV['RUBY_GC_OLDMALLOC_LIMIT_MAX'] = '134217728'
    
    # Enable GC profiling
    GC::Profiler.enable
  end
  
  def self.log_gc_stats
    stats = GC.stat
    
    puts "=== GC Statistics ==="
    puts "Total collections: #{stats[:count]}"
    puts "Heap slots live: #{stats[:heap_live_slots]}"
    puts "Heap slots free: #{stats[:heap_free_slots]}"
    puts "Memory allocated: #{stats[:total_allocated_objects]}"
    puts "Memory freed: #{stats[:total_freed_objects]}"
    puts "GC time: #{GC::Profiler.total_time}s"
    
    # Log to monitoring system
    if defined?(StatsD)
      StatsD.gauge('ruby.gc.live_slots', stats[:heap_live_slots])
      StatsD.gauge('ruby.gc.free_slots', stats[:heap_free_slots])
      StatsD.timing('ruby.gc.time', GC::Profiler.total_time * 1000)
    end
  end
  
  def self.optimize_for_memory
    # Trigger full GC and compaction
    GC.start(full_mark: true, immediate_sweep: true)
    GC.compact if GC.respond_to?(:compact)
    
    log_gc_stats
  end
end

# Production monitoring
at_exit do
  GCProfiler.log_gc_stats
end

Load path management in production requires careful ordering and validation. Applications should minimize load path entries and validate library versions during startup.

class LoadPathManager
  SYSTEM_PATHS = %w[
    /usr/lib/ruby
    /usr/local/lib/ruby
  ].freeze
  
  def self.configure_for_production
    # Clear development-specific paths
    $LOAD_PATH.reject! { |path| path.include?('/tmp/') || path.include?('development') }
    
    # Add application-specific paths first
    app_lib_path = File.expand_path('../lib', __dir__)
    vendor_path = File.expand_path('../vendor/lib', __dir__)
    
    $LOAD_PATH.unshift(app_lib_path) if File.directory?(app_lib_path)
    $LOAD_PATH.unshift(vendor_path) if File.directory?(vendor_path)
    
    # Validate critical libraries
    validate_required_libraries
    
    # Log final load path for debugging
    log_load_path_info
  end
  
  def self.validate_required_libraries
    required_libs = %w[json yaml uri net/http]
    
    required_libs.each do |lib|
      begin
        require lib
      rescue LoadError => error
        raise "Failed to load required library #{lib}: #{error.message}"
      end
    end
  end
  
  def self.log_load_path_info
    puts "=== Load Path Configuration ==="
    puts "Total paths: #{$LOAD_PATH.size}"
    
    system_paths = $LOAD_PATH.select { |path| SYSTEM_PATHS.any? { |sys| path.start_with?(sys) } }
    app_paths = $LOAD_PATH - system_paths
    
    puts "Application paths: #{app_paths.size}"
    app_paths.first(5).each { |path| puts "  #{path}" }
    
    puts "System paths: #{system_paths.size}"
    system_paths.first(3).each { |path| puts "  #{path}" }
  end
end

# Production initialization
LoadPathManager.configure_for_production

Reference

Command Line Options

Option Parameters Description
-c None Check syntax only, do not execute
-d None Enable debug mode (sets $DEBUG = true)
-e 'code' Execute code from command line
-I directory Add directory to load path
-r library Require library before execution
-v None Print version and enable verbose mode
-w None Enable verbose warnings (sets $VERBOSE = true)
-W level Set warning level (0=silence, 1=medium, 2=verbose)
--copyright None Print copyright information
--version None Print version information only

Environment Variables

Variable Type Default Description
RUBY_GC_HEAP_INIT_SLOTS Integer 10000 Initial heap slots
RUBY_GC_HEAP_FREE_SLOTS Integer 4096 Free slots maintained
RUBY_GC_HEAP_GROWTH_FACTOR Float 1.8 Heap growth multiplier
RUBY_GC_HEAP_GROWTH_MAX_SLOTS Integer 0 Maximum heap growth per GC
RUBY_GC_OLDMALLOC_LIMIT Integer 16MB Old generation malloc limit
RUBY_GC_OLDMALLOC_LIMIT_MAX Integer 128MB Maximum old generation limit
RUBY_THREAD_MACHINE_STACK_SIZE Integer 131072 Machine stack size (bytes)
RUBY_THREAD_VM_STACK_SIZE Integer 131072 VM stack size (bytes)
RUBY_EXTERNAL_ENCODING String System Default external encoding
RUBY_INTERNAL_ENCODING String None Default internal encoding

Global Variables

Variable Type Description
$VERBOSE Boolean/Nil Warning level control
$DEBUG Boolean Debug mode flag
$SAFE Integer Safe level (deprecated)
$LOAD_PATH Array Library search paths
$LOADED_FEATURES Array Loaded library files
$0 String Script name
$$ Integer Process ID
$? Process::Status Last command exit status

GC Configuration Values

Setting Range Impact Notes
HEAP_INIT_SLOTS 1000-100000 Startup memory Higher values reduce early GC
HEAP_GROWTH_FACTOR 1.1-3.0 Memory growth rate Lower values reduce memory usage
HEAP_GROWTH_MAX_SLOTS 0-50000 Growth cap per GC 0 means unlimited
OLDMALLOC_LIMIT 8MB-64MB Old object threshold Affects major GC frequency

Encoding Names

Encoding Aliases Description
UTF-8 utf8 Unicode transformation format
ASCII-8BIT binary Binary data encoding
US-ASCII ascii 7-bit ASCII encoding
ISO-8859-1 latin1 Latin alphabet encoding
Windows-1252 cp1252 Windows Western encoding
EUC-JP eucjp Japanese encoding
Shift_JIS sjis Japanese encoding

Warning Levels

Level Setting Behavior
0 $VERBOSE = nil Suppress all warnings
1 $VERBOSE = false Show important warnings only
2 $VERBOSE = true Show all warnings and deprecations

Load Path Priority

  1. Current directory (if -I . specified)
  2. Directories from -I options (in order)
  3. Directories from $RUBYLIB environment variable
  4. Application-specific paths added to $LOAD_PATH
  5. Gem installation directories
  6. Ruby standard library directories
  7. Site-specific directories
  8. System Ruby directories