Last active
June 25, 2022 14:54
-
-
Save jgaskins/ecc0fc90d78cdec63c31e0ce5544faa1 to your computer and use it in GitHub Desktop.
Benchmarking redis gem vs hiredis vs custom Redis client
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
require 'bundler/inline' | |
require 'socket' | |
class MyRedis | |
CRLF = "\r\n" | |
def initialize | |
@connection = TCPSocket.new('localhost', 6379) | |
@connection.sync = false | |
end | |
def get(key) | |
@connection << "*2\r\n$3\r\nget\r\n$#{key.bytesize}\r\n#{key}\r\n" | |
@connection.flush | |
result = @connection.gets | |
if result.start_with?('$') | |
value = '' | |
bytesize = result.tap { |r| r[0] = '' }.to_i | |
return nil if bytesize < 0 # Key does not exist | |
@connection.read bytesize + 2, value | |
value.chomp! CRLF | |
value | |
else | |
raise "idk what to do with this: #{result.inspect}" | |
end | |
end | |
end | |
gemfile true do | |
source 'https://rubygems.org' | |
gem 'redis' | |
gem 'hiredis' | |
gem 'benchmark-ips' | |
end | |
require 'benchmark' | |
require 'benchmark/ips' | |
require 'redis' | |
require 'hiredis' | |
redis = Redis.new(driver: :ruby) | |
hiredis = Redis.new(driver: :hiredis) | |
myredis = MyRedis.new | |
key = "foo" | |
cpu_time_iterations = 100_000 | |
# Quick functionality check on our custom Redis | |
redis.set key, "test" | |
if (myredis_value = myredis.get(key)) == (redis_value = redis.get(key)) | |
puts "Cache-hit function check passed" | |
else | |
raise "Value mismatch. Redis: #{redis_value.inspect}, MyRedis: #{myredis_value.inspect}" | |
end | |
redis.del key | |
if myredis_value = myredis.get(key).nil? | |
puts "Cache-miss function check passed" | |
else | |
raise "MyRedis cache miss broken: #{myredis_value.inspect}" | |
end | |
puts | |
puts "Cache hit (returns a 2KB string)" | |
redis.set key, "." * 2048 # 2KB cache entry | |
Benchmark.ips do |x| | |
x.report("ruby") { redis.get key } | |
x.report("hiredis") { hiredis.get key } | |
x.report("myredis") { myredis.get key } | |
x.compare! | |
end | |
puts | |
puts "Cache hit CPU time" | |
puts "ruby : #{Benchmark.measure { cpu_time_iterations.times { redis.get key } }.total}" | |
puts "hiredis: #{Benchmark.measure { cpu_time_iterations.times { hiredis.get key } }.total}" | |
puts "myredis: #{Benchmark.measure { cpu_time_iterations.times { myredis.get key } }.total}" | |
puts | |
puts "Cache miss (returns nil)" | |
redis.del key | |
Benchmark.ips do |x| | |
x.report("ruby") { redis.get key } | |
x.report("hiredis") { hiredis.get key } | |
x.report("myredis") { myredis.get key } | |
x.compare! | |
end | |
puts | |
puts "Cache miss CPU time" | |
puts "ruby : #{Benchmark.measure { cpu_time_iterations.times { redis.get key } }.total}" | |
puts "hiredis: #{Benchmark.measure { cpu_time_iterations.times { hiredis.get key } }.total}" | |
puts "myredis: #{Benchmark.measure { cpu_time_iterations.times { myredis.get key } }.total}" |
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
Fetching gem metadata from https://rubygems.org/.... | |
Resolving dependencies... | |
Using benchmark-ips 2.8.4 | |
Using bundler 2.2.3 | |
Using hiredis 0.6.3 | |
Using redis 4.2.5 | |
Cache-hit function check passed | |
Cache-miss function check passed | |
Cache hit (returns a 2KB string) | |
Warming up -------------------------------------- | |
ruby 1.857k i/100ms | |
hiredis 3.124k i/100ms | |
myredis 3.184k i/100ms | |
Calculating ------------------------------------- | |
ruby 22.082k (±14.1%) i/s - 107.706k in 5.021179s | |
hiredis 31.506k (± 1.7%) i/s - 159.324k in 5.058568s | |
myredis 31.997k (± 2.8%) i/s - 162.384k in 5.079019s | |
Comparison: | |
myredis: 31997.4 i/s | |
hiredis: 31505.6 i/s - same-ish: difference falls within error | |
ruby: 22081.8 i/s - 1.45x (± 0.00) slower | |
Cache hit CPU time | |
ruby : 3.7590459999999997 | |
hiredis: 1.9650980000000011 | |
myredis: 1.7395270000000007 | |
Cache miss (returns nil) | |
Warming up -------------------------------------- | |
ruby 2.666k i/100ms | |
hiredis 3.352k i/100ms | |
myredis 3.440k i/100ms | |
Calculating ------------------------------------- | |
ruby 25.796k (± 8.2%) i/s - 127.968k in 5.006173s | |
hiredis 33.267k (± 1.0%) i/s - 167.600k in 5.038516s | |
myredis 34.693k (± 2.3%) i/s - 175.440k in 5.059694s | |
Comparison: | |
myredis: 34693.1 i/s | |
hiredis: 33267.0 i/s - 1.04x (± 0.00) slower | |
ruby: 25795.8 i/s - 1.34x (± 0.00) slower | |
Cache miss CPU time | |
ruby : 3.0532809999999984 | |
hiredis: 1.840083 | |
myredis: 1.5741099999999975 |
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
Fetching gem metadata from https://rubygems.org/.... | |
Resolving dependencies... | |
Using bundler 2.2.15 | |
Using hiredis 0.6.3 | |
Using redis 4.2.5 | |
Using benchmark-ips 2.8.4 | |
Cache-hit function check passed | |
Cache-miss function check passed | |
Cache hit (returns a 2KB string) | |
Warming up -------------------------------------- | |
ruby 2.638k i/100ms | |
hiredis 5.080k i/100ms | |
myredis 5.741k i/100ms | |
Calculating ------------------------------------- | |
ruby 35.924k (±12.0%) i/s - 176.746k in 5.013467s | |
hiredis 52.624k (± 4.7%) i/s - 264.160k in 5.034100s | |
myredis 59.541k (± 1.1%) i/s - 298.532k in 5.014476s | |
Comparison: | |
myredis: 59541.4 i/s | |
hiredis: 52623.8 i/s - 1.13x (± 0.00) slower | |
ruby: 35924.1 i/s - 1.66x (± 0.00) slower | |
Cache hit CPU time | |
ruby : 1.751384999999999 | |
hiredis: 0.9159620000000004 | |
myredis: 0.6444190000000001 | |
Cache miss (returns nil) | |
Warming up -------------------------------------- | |
ruby 4.234k i/100ms | |
hiredis 5.594k i/100ms | |
myredis 6.340k i/100ms | |
Calculating ------------------------------------- | |
ruby 42.602k (± 9.1%) i/s - 211.700k in 5.020637s | |
hiredis 55.257k (± 4.7%) i/s - 279.700k in 5.074557s | |
myredis 63.400k (± 1.6%) i/s - 317.000k in 5.001319s | |
Comparison: | |
myredis: 63399.9 i/s | |
hiredis: 55256.9 i/s - 1.15x (± 0.00) slower | |
ruby: 42601.6 i/s - 1.49x (± 0.00) slower | |
Cache miss CPU time | |
ruby : 1.417432999999999 | |
hiredis: 0.832987000000001 | |
myredis: 0.5722979999999982 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment