Skip to content

Commit d7b508a

Browse files
authored
perf: add an environment variable to be able to configure a data type of slots and nodes mapping (#283)
1 parent b752d9b commit d7b508a

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

lib/redis_client/cluster/node.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Node
1717
MIN_SLOT = 0
1818
MAX_SLOT = SLOT_SIZE - 1
1919
MAX_STARTUP_SAMPLE = Integer(ENV.fetch('REDIS_CLIENT_MAX_STARTUP_SAMPLE', 3))
20+
USE_CHAR_ARRAY_SLOT = Integer(ENV.fetch('REDIS_CLIENT_USE_CHAR_ARRAY_SLOT', 1)) == 1 # less memory consumption, but slow
2021
IGNORE_GENERIC_CONFIG_KEYS = %i[url host port path].freeze
2122
DEAD_FLAGS = %w[fail? fail handshake noaddr noflags].freeze
2223
ROLE_FLAGS = %w[master slave].freeze
@@ -310,7 +311,7 @@ def build_slot_node_mappings(node_info_list)
310311
end
311312

312313
def make_array_for_slot_node_mappings(node_info_list)
313-
return Array.new(SLOT_SIZE) if node_info_list.count(&:primary?) > 256
314+
return Array.new(SLOT_SIZE) if !USE_CHAR_ARRAY_SLOT || node_info_list.count(&:primary?) > 256
314315

315316
primary_node_keys = node_info_list.select(&:primary?).map(&:node_key)
316317
::RedisClient::Cluster::Node::CharArray.new(SLOT_SIZE, primary_node_keys)

test/ips_slot_node_mapping.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
require 'benchmark/ips'
4+
require 'redis_cluster_client'
5+
6+
module IpsSlotNodeMapping
7+
ELEMENTS = %w[foo bar baz].freeze
8+
SIZE = ::RedisClient::Cluster::Node::SLOT_SIZE
9+
10+
module_function
11+
12+
def run
13+
ca = ::RedisClient::Cluster::Node::CharArray.new(SIZE, ELEMENTS)
14+
arr = Array.new(SIZE)
15+
16+
print_letter('Mappings between slots and nodes')
17+
fullfill(ca)
18+
fullfill(arr)
19+
bench({ ca.class.name.split('::').last => ca, arr.class.name => arr })
20+
end
21+
22+
def print_letter(title)
23+
print "################################################################################\n"
24+
print "# #{title}\n"
25+
print "################################################################################\n"
26+
print "\n"
27+
end
28+
29+
def fullfill(arr)
30+
SIZE.times { |i| arr[i] = ELEMENTS[i % ELEMENTS.size] }
31+
end
32+
33+
def bench(subjects)
34+
Benchmark.ips do |x|
35+
x.time = 5
36+
x.warmup = 1
37+
38+
subjects.each do |subtitle, arr|
39+
x.report(subtitle) do
40+
arr[0]
41+
end
42+
end
43+
44+
x.compare!
45+
end
46+
end
47+
end
48+
49+
IpsSlotNodeMapping.run

test/redis_client/cluster/test_node.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ def test_make_array_for_slot_node_mappings_optimized
488488

489489
want = node_info_list.first.node_key
490490
got = @test_node.send(:make_array_for_slot_node_mappings, node_info_list)
491-
assert_instance_of(::RedisClient::Cluster::Node::CharArray, got)
491+
assert_instance_of(::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT ? ::RedisClient::Cluster::Node::CharArray : Array, got)
492492
::RedisClient::Cluster::Node::SLOT_SIZE.times do |i|
493493
got[i] = want
494494
assert_equal(want, got[i], "Case: #{i}")
@@ -521,19 +521,19 @@ def test_make_array_for_slot_node_mappings_max_shard_size
521521
end
522522

523523
got = @test_node.send(:make_array_for_slot_node_mappings, node_info_list)
524-
assert_instance_of(::RedisClient::Cluster::Node::CharArray, got)
524+
assert_instance_of(::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT ? ::RedisClient::Cluster::Node::CharArray : Array, got)
525525

526526
::RedisClient::Cluster::Node::SLOT_SIZE.times { |i| got[i] = node_info_list.first.node_key }
527527

528528
got[0] = 'newbie:6379'
529529
assert_equal('newbie:6379', got[0])
530-
assert_raises(RangeError) { got[0] = 'zombie:6379' }
530+
assert_raises(RangeError) { got[0] = 'zombie:6379' } if ::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT
531531

532-
assert_raises(IndexError) { got[-1] = 'newbie:6379' }
533-
assert_raises(IndexError) { got[-1] }
532+
assert_raises(IndexError) { got[-1] = 'newbie:6379' } if ::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT
533+
assert_raises(IndexError) { got[-1] } if ::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT
534534

535535
got[16_384] = 'newbie:6379'
536-
assert_nil(got[16_384])
536+
assert_nil(got[16_384]) if ::RedisClient::Cluster::Node::USE_CHAR_ARRAY_SLOT
537537
end
538538

539539
def test_build_replication_mappings_regular

0 commit comments

Comments
 (0)