Skip to content

Commit 92a983a

Browse files
authored
Merge pull request #912 from zanker-stripe/optimize-slot-new
Optimized initialization of Redis::Cluster
2 parents aebc693 + 92752e7 commit 92a983a

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

benchmarking/cluster_slot.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
require 'redis'
4+
require 'benchmark'
5+
6+
N = (ARGV.first || 100000).to_i
7+
8+
available_slots = {
9+
"127.0.0.1:7000" => [0..5460],
10+
"127.0.0.1:7003" => [0..5460],
11+
"127.0.0.1:7001" => [5461..10922],
12+
"127.0.0.1:7004" => [5461..10922],
13+
"127.0.0.1:7002" => [10923..16383],
14+
"127.0.0.1:7005" => [10923..16383]
15+
}
16+
17+
node_flags = {
18+
"127.0.0.1:7000" => "master",
19+
"127.0.0.1:7002" => "master",
20+
"127.0.0.1:7001" => "master",
21+
"127.0.0.1:7005" => "slave",
22+
"127.0.0.1:7004" => "slave",
23+
"127.0.0.1:7003" => "slave"
24+
}
25+
26+
Benchmark.bmbm do |bm|
27+
bm.report('Slot.new') do
28+
allocs = GC.stat(:total_allocated_objects)
29+
30+
N.times do
31+
Redis::Cluster::Slot.new(available_slots, node_flags, false)
32+
end
33+
34+
puts GC.stat(:total_allocated_objects) - allocs
35+
end
36+
end

lib/redis/cluster/slot.rb

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# frozen_string_literal: true
22

3-
require 'set'
4-
53
class Redis
64
class Cluster
75
# Keep slot and node key map for Redis Cluster Client
@@ -28,11 +26,20 @@ def find_node_key_of_slave(slot)
2826
return nil unless exists?(slot)
2927
return find_node_key_of_master(slot) if replica_disabled?
3028

31-
@map[slot][:slaves].to_a.sample
29+
@map[slot][:slaves].sample
3230
end
3331

3432
def put(slot, node_key)
35-
assign_node_key(@map, slot, node_key)
33+
# Since we're sharing a hash for build_slot_node_key_map, duplicate it
34+
# if it already exists instead of preserving as-is.
35+
@map[slot] = @map[slot] ? @map[slot].dup : { master: nil, slaves: [] }
36+
37+
if master?(node_key)
38+
@map[slot][:master] = node_key
39+
elsif !@map[slot][:slaves].include?(node_key)
40+
@map[slot][:slaves] << node_key
41+
end
42+
3643
nil
3744
end
3845

@@ -52,20 +59,27 @@ def slave?(node_key)
5259

5360
# available_slots is mapping of node_key to list of slot ranges
5461
def build_slot_node_key_map(available_slots)
55-
available_slots.each_with_object({}) do |(node_key, slots_arr), acc|
56-
slots_arr.each do |slots|
57-
slots.each { |slot| assign_node_key(acc, slot, node_key) }
62+
by_ranges = {}
63+
available_slots.each do |node_key, slots_arr|
64+
by_ranges[slots_arr] ||= { master: nil, slaves: [] }
65+
66+
if master?(node_key)
67+
by_ranges[slots_arr][:master] = node_key
68+
elsif !by_ranges[slots_arr][:slaves].include?(node_key)
69+
by_ranges[slots_arr][:slaves] << node_key
5870
end
5971
end
60-
end
6172

62-
def assign_node_key(mappings, slot, node_key)
63-
mappings[slot] ||= { master: nil, slaves: ::Set.new }
64-
if master?(node_key)
65-
mappings[slot][:master] = node_key
66-
else
67-
mappings[slot][:slaves].add(node_key)
73+
by_slot = {}
74+
by_ranges.each do |slots_arr, nodes|
75+
slots_arr.each do |slots|
76+
slots.each do |slot|
77+
by_slot[slot] = nodes
78+
end
79+
end
6880
end
81+
82+
by_slot
6983
end
7084
end
7185
end

0 commit comments

Comments
 (0)