Skip to content

Commit 76cb715

Browse files
committed
perf: command builder should be called once
1 parent ff2969d commit 76cb715

File tree

8 files changed

+116
-17
lines changed

8 files changed

+116
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.bundle
22
*.gem
3+
*.json
34
Gemfile.lock

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ gem 'rubocop-minitest', require: false
1515
gem 'rubocop-performance', require: false
1616
gem 'rubocop-rake', require: false
1717
gem 'stackprof', platform: :mri
18+
gem 'vernier', platform: :mri
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# frozen_string_literal: true
2+
3+
class RedisClient
4+
class Cluster
5+
module NoopCommandBuilder
6+
module_function
7+
8+
def generate(args, _kwargs = nil)
9+
args
10+
end
11+
end
12+
end
13+
end

lib/redis_client/cluster/pipeline.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'redis_client'
44
require 'redis_client/cluster/errors'
5+
require 'redis_client/cluster/noop_command_builder'
56
require 'redis_client/connection_mixin'
67
require 'redis_client/middlewares'
78
require 'redis_client/pooled'
@@ -229,7 +230,7 @@ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Met
229230

230231
def append_pipeline(node_key)
231232
@pipelines ||= {}
232-
@pipelines[node_key] ||= ::RedisClient::Cluster::Pipeline::Extended.new(@command_builder)
233+
@pipelines[node_key] ||= ::RedisClient::Cluster::Pipeline::Extended.new(::RedisClient::Cluster::NoopCommandBuilder)
233234
@pipelines[node_key].add_outer_index(@size)
234235
@size += 1
235236
@pipelines[node_key]

lib/redis_client/cluster/transaction.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'redis_client'
44
require 'redis_client/cluster/errors'
5+
require 'redis_client/cluster/noop_command_builder'
56
require 'redis_client/cluster/pipeline'
67

78
class RedisClient
@@ -18,7 +19,7 @@ def initialize(router, command_builder, node: nil, slot: nil, asking: false)
1819
@router = router
1920
@command_builder = command_builder
2021
@retryable = true
21-
@pipeline = ::RedisClient::Pipeline.new(@command_builder)
22+
@pipeline = ::RedisClient::Pipeline.new(::RedisClient::Cluster::NoopCommandBuilder)
2223
@pending_commands = []
2324
@node = node
2425
prepare_tx unless @node.nil?

lib/redis_client/cluster_config.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
require 'redis_client/cluster'
66
require 'redis_client/cluster/errors'
77
require 'redis_client/cluster/node_key'
8+
require 'redis_client/cluster/noop_command_builder'
89
require 'redis_client/command_builder'
910

1011
class RedisClient
@@ -64,7 +65,7 @@ def initialize( # rubocop:disable Metrics/ParameterLists
6465
end
6566

6667
def inspect
67-
"#<#{self.class.name} #{startup_nodes.values}>"
68+
"#<#{self.class.name} #{startup_nodes.values.map { |v| v.except(:command_builder) }}>"
6869
end
6970

7071
def read_timeout
@@ -187,6 +188,7 @@ def build_startup_nodes(configs)
187188
def augment_client_config(config)
188189
config = @client_config.merge(config)
189190
config = config.merge(host: @fixed_hostname) unless @fixed_hostname.empty?
191+
config[:command_builder] = ::RedisClient::Cluster::NoopCommandBuilder # prevent twice call
190192
config
191193
end
192194
end

test/prof_stack2.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# frozen_string_literal: true
2+
3+
require 'vernier'
4+
require 'redis_cluster_client'
5+
require 'testing_constants'
6+
7+
module ProfStack2
8+
SIZE = 40
9+
ATTEMPTS = 1000
10+
11+
module_function
12+
13+
def run
14+
client = make_client
15+
prepare(client)
16+
17+
case mode = ENV.fetch('PROFILE_MODE', :single).to_sym
18+
when :single
19+
execute(client, mode) do |client|
20+
ATTEMPTS.times { |i| client.call('GET', "key#{i}") }
21+
end
22+
when :transaction
23+
execute(client, mode) do |client|
24+
ATTEMPTS.times do |i|
25+
client.multi do |tx|
26+
SIZE.times do |j|
27+
n = SIZE * i + j
28+
tx.call('SET', "{group:#{i}}:key:#{n}", n)
29+
end
30+
end
31+
end
32+
end
33+
when :pipeline
34+
execute(client, mode) do |client|
35+
ATTEMPTS.times do |i|
36+
client.pipelined do |pi|
37+
SIZE.times do |j|
38+
n = SIZE * i + j
39+
pi.call('GET', "key#{n}")
40+
end
41+
end
42+
end
43+
end
44+
end
45+
end
46+
47+
def execute(client, mode)
48+
Vernier.profile(out: "vernier_#{mode}.json") do
49+
yield(client)
50+
end
51+
end
52+
53+
def make_client
54+
::RedisClient.cluster(
55+
nodes: TEST_NODE_URIS,
56+
replica: true,
57+
replica_affinity: :random,
58+
fixed_hostname: TEST_FIXED_HOSTNAME,
59+
# concurrency: { model: :on_demand, size: 6 },
60+
# concurrency: { model: :pooled, size: 6 },
61+
concurrency: { model: :none },
62+
**TEST_GENERIC_OPTIONS
63+
).new_client
64+
end
65+
66+
def prepare(client)
67+
ATTEMPTS.times do |i|
68+
client.pipelined do |pi|
69+
SIZE.times do |j|
70+
n = SIZE * i + j
71+
pi.call('SET', "key#{n}", "val#{n}")
72+
end
73+
end
74+
end
75+
end
76+
end
77+
78+
ProfStack2.run

test/redis_client/test_cluster_config.rb

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,38 +38,38 @@ def test_startup_nodes
3838
{
3939
config: ::RedisClient::ClusterConfig.new,
4040
want: {
41-
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379 }
41+
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
4242
}
4343
},
4444
{
4545
config: ::RedisClient::ClusterConfig.new(replica: true),
4646
want: {
47-
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379 }
47+
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
4848
}
4949
},
5050
{
5151
config: ::RedisClient::ClusterConfig.new(fixed_hostname: 'endpoint.example.com'),
5252
want: {
53-
'127.0.0.1:6379' => { host: 'endpoint.example.com', port: 6379 }
53+
'127.0.0.1:6379' => { host: 'endpoint.example.com', port: 6379, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
5454
}
5555
},
5656
{
5757
config: ::RedisClient::ClusterConfig.new(timeout: 1),
5858
want: {
59-
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, timeout: 1 }
59+
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, timeout: 1, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
6060
}
6161
},
6262
{
6363
config: ::RedisClient::ClusterConfig.new(nodes: ['redis://1.2.3.4:1234', 'rediss://5.6.7.8:5678']),
6464
want: {
65-
'1.2.3.4:1234' => { host: '1.2.3.4', port: 1234 },
66-
'5.6.7.8:5678' => { host: '5.6.7.8', port: 5678, ssl: true }
65+
'1.2.3.4:1234' => { host: '1.2.3.4', port: 1234, command_builder: ::RedisClient::Cluster::NoopCommandBuilder },
66+
'5.6.7.8:5678' => { host: '5.6.7.8', port: 5678, ssl: true, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
6767
}
6868
},
6969
{
7070
config: ::RedisClient::ClusterConfig.new(custom: { foo: 'bar' }),
7171
want: {
72-
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, custom: { foo: 'bar' } }
72+
'127.0.0.1:6379' => { host: '127.0.0.1', port: 6379, custom: { foo: 'bar' }, command_builder: ::RedisClient::Cluster::NoopCommandBuilder }
7373
}
7474
}
7575
].each_with_index do |c, idx|
@@ -182,13 +182,15 @@ def test_client_config_for_node
182182
nodes: ['redis://username:[email protected]:1234', 'rediss://5.6.7.8:5678'],
183183
custom: { foo: 'bar' }
184184
)
185-
assert_equal({
186-
host: '9.9.9.9',
187-
port: 9999,
188-
username: 'username',
189-
password: 'password',
190-
custom: { foo: 'bar' }
191-
}, config.client_config_for_node('9.9.9.9:9999'))
185+
want = {
186+
host: '9.9.9.9',
187+
port: 9999,
188+
username: 'username',
189+
password: 'password',
190+
custom: { foo: 'bar' },
191+
command_builder: ::RedisClient::Cluster::NoopCommandBuilder
192+
}
193+
assert_equal(want, config.client_config_for_node('9.9.9.9:9999'))
192194
end
193195

194196
def test_client_config_id

0 commit comments

Comments
 (0)