Skip to content

Instantly share code, notes, and snippets.

@mhenrixon
Last active January 9, 2025 09:19
Show Gist options
  • Save mhenrixon/e5cbb65c62862c82675692bd3c715fc8 to your computer and use it in GitHub Desktop.
Save mhenrixon/e5cbb65c62862c82675692bd3c715fc8 to your computer and use it in GitHub Desktop.
Benchmark and compare various ways to access the ENV variable in ruby
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'benchmark/ips'
require 'benchmark/memory'
# Set up test environment variables
ENV['TEST_KEY1'] = 'some_value'
ENV['TEST_KEY2'] = 'another_value'
ENV['TEST_KEY3'] = 'third_value'
# Create class similar to Rails.application.credentials
class MockCredentials
def initialize
@values = {
test_key1: 'some_value',
test_key2: 'another_value',
test_key3: 'third_value'
}
end
def dig(*keys)
@values.dig(*keys)
end
end
# Create cached hash version
CACHED_ENV = ENV.to_h
credentials = MockCredentials.new
puts "Performance Benchmark (iterations per second):"
puts "============================================"
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report("ENV['KEY'] direct access") do
ENV['TEST_KEY1']
ENV['TEST_KEY2']
ENV['TEST_KEY3']
end
x.report("ENV.fetch direct access") do
ENV.fetch('TEST_KEY1')
ENV.fetch('TEST_KEY2')
ENV.fetch('TEST_KEY3')
end
x.report("Cached ENV hash access") do
CACHED_ENV['TEST_KEY1']
CACHED_ENV['TEST_KEY2']
CACHED_ENV['TEST_KEY3']
end
x.report("credentials-style access") do
credentials.dig(:test_key1)
credentials.dig(:test_key2)
credentials.dig(:test_key3)
end
x.compare!
end
puts "\nMemory Usage:"
puts "============="
Benchmark.memory do |x|
x.report("ENV['KEY'] direct access") do
100.times do
ENV['TEST_KEY1']
ENV['TEST_KEY2']
ENV['TEST_KEY3']
end
end
x.report("ENV.fetch direct access") do
100.times do
ENV.fetch('TEST_KEY1')
ENV.fetch('TEST_KEY2')
ENV.fetch('TEST_KEY3')
end
end
x.report("Cached ENV hash access") do
100.times do
CACHED_ENV['TEST_KEY1']
CACHED_ENV['TEST_KEY2']
CACHED_ENV['TEST_KEY3']
end
end
x.report("credentials-style access") do
100.times do
credentials.dig(:test_key1)
credentials.dig(:test_key2)
credentials.dig(:test_key3)
end
end
x.compare!
end
Performance Benchmark (iterations per second):
============================================
ruby 2.3.8p459 (2018-10-18 revision 65136) [aarch64-linux]
Warming up --------------------------------------
ENV['KEY'] direct access
153.285k i/100ms
ENV.fetch direct access
156.696k i/100ms
Cached ENV hash access
571.329k i/100ms
credentials-style access
257.128k i/100ms
Calculating -------------------------------------
ENV['KEY'] direct access
1.572M (± 1.3%) i/s (636.05 ns/i) - 7.971M in 5.070658s
ENV.fetch direct access
1.562M (± 1.8%) i/s (640.17 ns/i) - 7.835M in 5.017175s
Cached ENV hash access
5.702M (± 2.3%) i/s (175.39 ns/i) - 28.566M in 5.012782s
credentials-style access
2.602M (± 2.2%) i/s (384.27 ns/i) - 13.114M in 5.041605s
Comparison:
Cached ENV hash access: 5701655.1 i/s
credentials-style access: 2602305.8 i/s - 2.19x slower
ENV['KEY'] direct access: 1572197.8 i/s - 3.63x slower
ENV.fetch direct access: 1562085.0 i/s - 3.65x slower
Memory Usage:
=============
Calculating -------------------------------------
ENV['KEY'] direct access
24.000k memsize ( 0.000 retained)
600.000 objects ( 0.000 retained)
6.000 strings ( 0.000 retained)
ENV.fetch direct access
12.000k memsize ( 0.000 retained)
300.000 objects ( 0.000 retained)
3.000 strings ( 0.000 retained)
Cached ENV hash access
0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
credentials-style access
24.000k memsize ( 0.000 retained)
600.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
Comparison:
Cached ENV hash access: 0 allocated
ENV.fetch direct access: 12000 allocated - Infx more
ENV['KEY'] direct access: 24000 allocated - Infx more
credentials-style access: 24000 allocated - Infx more
Performance Benchmark (iterations per second):
============================================
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +PRISM [arm64-darwin24]
Warming up --------------------------------------
ENV['KEY'] direct access
146.202k i/100ms
ENV.fetch direct access
138.816k i/100ms
Cached ENV hash access
1.292M i/100ms
credentials-style access
441.103k i/100ms
Calculating -------------------------------------
ENV['KEY'] direct access
1.441M (± 1.6%) i/s (693.97 ns/i) - 7.310M in 5.074315s
ENV.fetch direct access
1.414M (± 2.0%) i/s (707.27 ns/i) - 7.080M in 5.009181s
Cached ENV hash access
14.212M (± 1.2%) i/s (70.36 ns/i) - 72.334M in 5.090395s
credentials-style access
4.616M (± 2.3%) i/s (216.66 ns/i) - 23.378M in 5.067600s
Comparison:
Cached ENV hash access: 14211933.1 i/s
credentials-style access: 4615607.5 i/s - 3.08x slower
ENV['KEY'] direct access: 1440994.2 i/s - 9.86x slower
ENV.fetch direct access: 1413890.8 i/s - 10.05x slower
Memory Usage:
=============
Calculating -------------------------------------
ENV['KEY'] direct access
12.000k memsize ( 0.000 retained)
300.000 objects ( 0.000 retained)
3.000 strings ( 0.000 retained)
ENV.fetch direct access
12.000k memsize ( 0.000 retained)
300.000 objects ( 0.000 retained)
3.000 strings ( 0.000 retained)
Cached ENV hash access
0.000 memsize ( 0.000 retained)
0.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
credentials-style access
12.000k memsize ( 0.000 retained)
300.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
Comparison:
Cached ENV hash access: 0 allocated
ENV['KEY'] direct access: 12000 allocated - Infx more
ENV.fetch direct access: 12000 allocated - Infx more
credentials-style access: 12000 allocated - Infx more
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment