Skip to content

Instantly share code, notes, and snippets.

@sorentwo
Created August 18, 2015 11:21
Show Gist options
  • Save sorentwo/cf9b602668228186b2cf to your computer and use it in GitHub Desktop.
Save sorentwo/cf9b602668228186b2cf to your computer and use it in GitHub Desktop.
Redis vs Lua payload reconstruction
require 'bundler'
Bundler.setup
require 'json'
require 'benchmark/ips'
require 'redis'
require 'securerandom'
REDIS = Redis.new(url: 'redis://localhost:6379/11')
def gen_post(id)
auth = JSON.dump(id: id, name: SecureRandom.hex(8))
post = JSON.dump(id: id, author_id: 3, title: SecureRandom.hex(16))
comm = JSON.dump(id: id, post_id: id, body: SecureRandom.hex(16))
{ "posts/#{id}" => post, "authors/#{id}" => auth, "comments/#{id}" => comm }
end
def construct_ruby
hashes = REDIS.multi do
('posts/0'..'posts/30').map { |key| REDIS.hgetall(key) }
end
array_backed_hash = Hash.new { |hash, key| hash[key] = [] }
payload = hashes.each_with_object(array_backed_hash) do |hash, memo|
hash.each do |key, val|
root, _ = key.split('/')
memo[root] << val
end
end
payload
end
SCRIPT = <<-LUA
local payload = {}
for _, key in ipairs(KEYS) do
local hash = redis.call('HGETALL', key)
for index = 1, #hash, 2 do
local field = hash[index]
local data = hash[index + 1]
local root = string.gsub(field, '(%a)([/\]%d*)', '%1')
if type(payload[root]) == "table" then
table.insert(payload[root], data)
else
payload[root] = {data}
end
end
end
return cjson.encode(payload)
LUA
def construct_lua
REDIS.evalsha(SHA, ('posts/1'..'posts/30').to_a)
end
REDIS.flushdb
SHA = REDIS.script(:load, SCRIPT)
posts = (1..30).map { |index| gen_post(index) }
posts.each_with_index do |post, index|
REDIS.hmset("posts/#{index}", post.to_a.flatten)
end
Benchmark.ips do |x|
x.report('ruby') { construct_ruby }
x.report('lua') { construct_lua }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment