Skip to content

Commit 4188cfd

Browse files
authored
chore: add some benchmarks for iteration per seconds (#266)
1 parent 044cc0d commit 4188cfd

File tree

7 files changed

+155
-46
lines changed

7 files changed

+155
-46
lines changed

.github/workflows/test.yaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
REDIS_CLIENT_MAX_STARTUP_SAMPLE: ${{ matrix.startup || '3' }}
5454
steps:
5555
- name: Check out code
56-
uses: actions/checkout@v3
56+
uses: actions/checkout@v4
5757
- name: Set up Ruby
5858
uses: ruby/setup-ruby@v1
5959
with:
@@ -80,7 +80,7 @@ jobs:
8080
DOCKER_COMPOSE_FILE: 'compose.nat.yaml'
8181
steps:
8282
- name: Check out code
83-
uses: actions/checkout@v3
83+
uses: actions/checkout@v4
8484
- name: Set up Ruby
8585
uses: ruby/setup-ruby@v1
8686
with:
@@ -135,7 +135,7 @@ jobs:
135135
runs-on: ubuntu-latest
136136
steps:
137137
- name: Check out code
138-
uses: actions/checkout@v3
138+
uses: actions/checkout@v4
139139
- name: Set up Ruby
140140
uses: ruby/setup-ruby@v1
141141
with:
@@ -155,7 +155,7 @@ jobs:
155155
DELAY_TIME: '1ms'
156156
steps:
157157
- name: Check out code
158-
uses: actions/checkout@v3
158+
uses: actions/checkout@v4
159159
- name: Set up Ruby
160160
uses: ruby/setup-ruby@v1
161161
with:
@@ -195,6 +195,8 @@ jobs:
195195
run: df -h
196196
- name: Run minitest
197197
run: bundle exec rake bench | grep BenchCommand | grep -v 'Envoy#bench_pipeline_echo\|Envoy#bench_single_echo' | sort
198+
- name: Run iteration per second
199+
run: bundle exec rake ips
198200
- name: Reset qdisc
199201
run: |
200202
for i in {5..9..2}
@@ -219,7 +221,7 @@ jobs:
219221
DOCKER_COMPOSE_FILE: 'compose.yaml'
220222
steps:
221223
- name: Check out code
222-
uses: actions/checkout@v3
224+
uses: actions/checkout@v4
223225
- name: Set up Ruby
224226
uses: ruby/setup-ruby@v1
225227
with:
@@ -251,7 +253,7 @@ jobs:
251253
REDIS_CLIENT_MAX_STARTUP_SAMPLE: '5'
252254
steps:
253255
- name: Check out code
254-
uses: actions/checkout@v3
256+
uses: actions/checkout@v4
255257
- name: Set up Ruby
256258
uses: ruby/setup-ruby@v1
257259
with:

lib/redis_client/cluster/concurrent_worker.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ def exec
2020
rescue StandardError => e
2121
self[:result] = e
2222
ensure
23+
done
24+
end
25+
26+
def done
2327
queue&.push(self)
28+
rescue ClosedQueueError
29+
# something was wrong
2430
end
2531
end
2632

@@ -69,6 +75,10 @@ def create(model: :on_demand)
6975
else raise ArgumentError, "Unknown model: #{model}"
7076
end
7177
end
78+
79+
def size
80+
MAX_WORKERS.positive? ? MAX_WORKERS : 5
81+
end
7282
end
7383
end
7484
end

lib/redis_client/cluster/concurrent_worker/on_demand.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@ class Cluster
55
module ConcurrentWorker
66
class OnDemand
77
def initialize
8-
size = ::RedisClient::Cluster::ConcurrentWorker::MAX_WORKERS
9-
size = size.positive? ? size : 5
10-
@q = SizedQueue.new(size)
8+
@q = SizedQueue.new(::RedisClient::Cluster::ConcurrentWorker.size)
119
end
1210

1311
def new_group(size:)
14-
raise ArgumentError, "size must be positive: #{size} given" unless size.positive?
15-
1612
::RedisClient::Cluster::ConcurrentWorker::Group.new(worker: self, size: size)
1713
end
1814

lib/redis_client/cluster/concurrent_worker/pooled.rb

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ def initialize
1515
end
1616

1717
def new_group(size:)
18-
raise ArgumentError, "size must be positive: #{size} given" unless size.positive?
19-
2018
reset if @pid != ::RedisClient::PIDCache.pid
2119
ensure_workers if @workers.first.nil?
2220
::RedisClient::Cluster::ConcurrentWorker::Group.new(worker: self, size: size)
@@ -37,30 +35,26 @@ def close
3735

3836
private
3937

40-
def ensure_workers
41-
@workers.size.times do |i|
42-
@workers[i] = spawn_worker unless @workers[i]&.alive?
43-
end
44-
end
45-
46-
def spawn_worker
47-
Thread.new(@q) do |q|
48-
loop { q.pop.exec }
49-
end
50-
end
51-
5238
def setup
5339
@q = Queue.new
54-
size = ::RedisClient::Cluster::ConcurrentWorker::MAX_WORKERS
55-
size = size.positive? ? size : 5
56-
@workers = Array.new(size)
40+
@workers = Array.new(::RedisClient::Cluster::ConcurrentWorker.size)
5741
@pid = ::RedisClient::PIDCache.pid
5842
end
5943

6044
def reset
6145
close
6246
setup
6347
end
48+
49+
def ensure_workers
50+
@workers.size.times do |i|
51+
@workers[i] = spawn_worker unless @workers[i]&.alive?
52+
end
53+
end
54+
55+
def spawn_worker
56+
Thread.new(@q) { |q| loop { q.pop.exec } }
57+
end
6458
end
6559
end
6660
end

test/ips_pipeline.rb

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@
44
require 'redis_cluster_client'
55
require 'testing_constants'
66

7-
module BenchPipeline
7+
module IpsPipeline
88
module_function
99

1010
ATTEMPTS = 100
1111

1212
def run
1313
on_demand = make_client(:on_demand)
1414
pooled = make_client(:pooled)
15-
prepare(on_demand, pooled)
16-
bench(on_demand, pooled)
15+
envoy = make_client_for_envoy
16+
cluster_proxy = make_client_for_cluster_proxy
17+
prepare(on_demand, pooled, envoy, cluster_proxy)
18+
print_letter('pipelined')
19+
bench(
20+
ondemand: on_demand,
21+
pooled: pooled,
22+
envoy: envoy,
23+
cproxy: cluster_proxy
24+
)
1725
end
1826

1927
def make_client(model)
@@ -25,32 +33,53 @@ def make_client(model)
2533
).new_client
2634
end
2735

28-
def prepare(on_demand, pooled)
29-
on_demand.pipelined do |pi|
30-
ATTEMPTS.times { |i| pi.call('SET', "key#{i}", "val#{i}") }
31-
end
36+
def make_client_for_envoy
37+
::RedisClient.config(
38+
**TEST_GENERIC_OPTIONS.merge(BENCH_ENVOY_OPTIONS)
39+
).new_client
40+
end
41+
42+
def make_client_for_cluster_proxy
43+
::RedisClient.config(
44+
**TEST_GENERIC_OPTIONS.merge(BENCH_REDIS_CLUSTER_PROXY_OPTIONS)
45+
).new_client
46+
end
3247

33-
pooled.pipelined do |pi|
34-
ATTEMPTS.times { |i| pi.call('SET', "key#{i}", "val#{i}") }
48+
def print_letter(title)
49+
print "################################################################################\n"
50+
print "# #{title}\n"
51+
print "################################################################################\n"
52+
print "\n"
53+
end
54+
55+
def prepare(*clients)
56+
clients.each do |client|
57+
client.pipelined do |pi|
58+
ATTEMPTS.times do |i|
59+
pi.call('SET', "key#{i}", "val#{i}")
60+
end
61+
end
3562
end
3663
end
3764

38-
def bench(on_demand, pooled)
65+
def bench(**kwargs)
3966
Benchmark.ips do |x|
4067
x.time = 5
4168
x.warmup = 1
4269

43-
x.report('on_demand') do
44-
on_demand.pipelined { |pi| ATTEMPTS.times { |i| pi.call('GET', "key#{i}") } }
45-
end
46-
47-
x.report('pooled') do
48-
pooled.pipelined { |pi| ATTEMPTS.times { |i| pi.call('GET', "key#{i}") } }
70+
kwargs.each do |key, client|
71+
x.report("pipelined: #{key}") do
72+
client.pipelined do |pi|
73+
ATTEMPTS.times do |i|
74+
pi.call('GET', "key#{i}")
75+
end
76+
end
77+
end
4978
end
5079

5180
x.compare!
5281
end
5382
end
5483
end
5584

56-
BenchPipeline.run
85+
IpsPipeline.run

test/ips_single.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 'benchmark/ips'
4+
require 'redis_cluster_client'
5+
require 'testing_constants'
6+
7+
module IpsSingle
8+
module_function
9+
10+
ATTEMPTS = 10
11+
12+
def run
13+
cli = make_client
14+
envoy = make_client_for_envoy
15+
cluster_proxy = make_client_for_cluster_proxy
16+
prepare(cli, envoy, cluster_proxy)
17+
print_letter('single')
18+
bench(
19+
cli: cli,
20+
envoy: envoy,
21+
cproxy: cluster_proxy
22+
)
23+
end
24+
25+
def make_client
26+
::RedisClient.cluster(
27+
nodes: TEST_NODE_URIS,
28+
fixed_hostname: TEST_FIXED_HOSTNAME,
29+
**TEST_GENERIC_OPTIONS
30+
).new_client
31+
end
32+
33+
def make_client_for_envoy
34+
::RedisClient.config(
35+
**TEST_GENERIC_OPTIONS.merge(BENCH_ENVOY_OPTIONS)
36+
).new_client
37+
end
38+
39+
def make_client_for_cluster_proxy
40+
::RedisClient.config(
41+
**TEST_GENERIC_OPTIONS.merge(BENCH_REDIS_CLUSTER_PROXY_OPTIONS)
42+
).new_client
43+
end
44+
45+
def print_letter(title)
46+
print "################################################################################\n"
47+
print "# #{title}\n"
48+
print "################################################################################\n"
49+
print "\n"
50+
end
51+
52+
def prepare(*clients)
53+
clients.each do |client|
54+
ATTEMPTS.times do |i|
55+
client.call('SET', "key#{i}", "val#{i}")
56+
end
57+
end
58+
end
59+
60+
def bench(**kwargs)
61+
Benchmark.ips do |x|
62+
x.time = 5
63+
x.warmup = 1
64+
65+
kwargs.each do |key, client|
66+
x.report("single: #{key}") do
67+
ATTEMPTS.times do |i|
68+
client.call('GET', "key#{i}")
69+
end
70+
end
71+
end
72+
73+
x.compare!
74+
end
75+
end
76+
end
77+
78+
IpsSingle.run

test/redis_client/cluster/test_node.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_load_info
6060
[
6161
{
6262
params: { options: TEST_NODE_OPTIONS, kwargs: TEST_GENERIC_OPTIONS },
63-
want: { size: TEST_NODE_OPTIONS.size }
63+
want: { size: TEST_NUMBER_OF_NODES }
6464
},
6565
{
6666
params: { options: { '127.0.0.1:11211' => { host: '127.0.0.1', port: 11_211 } }, kwargs: TEST_GENERIC_OPTIONS },

0 commit comments

Comments
 (0)