cztop 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +16 -0
- data/README.md +61 -56
- data/cztop.gemspec +2 -4
- data/lib/cztop/actor.rb +26 -22
- data/lib/cztop/certificate.rb +19 -11
- data/lib/cztop/message.rb +5 -1
- data/lib/cztop/send_receive_methods.rb +106 -2
- data/lib/cztop/socket/types.rb +18 -0
- data/lib/cztop/version.rb +1 -1
- data/lib/cztop/zsock_options.rb +16 -2
- metadata +3 -66
- data/.github/workflows/coverage.yml +0 -20
- data/.github/workflows/draft_api.yml +0 -27
- data/.github/workflows/stable_api.yml +0 -26
- data/.gitignore +0 -10
- data/.projections.json +0 -4
- data/.rspec +0 -2
- data/.rubocop.yml +0 -175
- data/.yardopts +0 -1
- data/Rakefile +0 -6
- data/ci/install-libczmq +0 -22
- data/ci/install-libzmq +0 -22
- data/examples/async/.gitignore +0 -1
- data/examples/async/Gemfile +0 -5
- data/examples/async/README.md +0 -1
- data/examples/async/async.rb +0 -35
- data/examples/ruby_actor/actor.rb +0 -100
- data/examples/simple_req_rep/rep.rb +0 -12
- data/examples/simple_req_rep/req.rb +0 -35
- data/examples/taxi_system/.gitignore +0 -2
- data/examples/taxi_system/Makefile +0 -2
- data/examples/taxi_system/README.gsl +0 -115
- data/examples/taxi_system/README.md +0 -276
- data/examples/taxi_system/broker.rb +0 -97
- data/examples/taxi_system/client.rb +0 -34
- data/examples/taxi_system/generate_keys.rb +0 -24
- data/examples/taxi_system/start_broker.sh +0 -2
- data/examples/taxi_system/start_clients.sh +0 -11
- data/examples/weather_pub_sub/pub.rb +0 -24
- data/examples/weather_pub_sub/sub.rb +0 -33
- data/lib/cztop/async.rb +0 -124
- data/perf/README.md +0 -80
- data/perf/inproc_lat.rb +0 -49
- data/perf/inproc_thru.rb +0 -42
- data/perf/local_lat.rb +0 -35
- data/perf/remote_lat.rb +0 -26
data/lib/cztop/async.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cztop'
|
4
|
-
require 'async/io'
|
5
|
-
|
6
|
-
module Async
|
7
|
-
module IO
|
8
|
-
|
9
|
-
# Wrapper for CZTop sockets.
|
10
|
-
#
|
11
|
-
# @example
|
12
|
-
# Async do |task|
|
13
|
-
# socket = CZTop::Socket::REP.new("ipc:///tmp/req_rep_example")
|
14
|
-
# socket.options.rcvtimeo = 3
|
15
|
-
# io = Async::IO.try_convert socket
|
16
|
-
# msg = io.receive
|
17
|
-
# io << msg.to_a.map(&:upcase)
|
18
|
-
# end
|
19
|
-
|
20
|
-
class CZTopSocket < Generic
|
21
|
-
wraps ::CZTop::Socket::REQ
|
22
|
-
wraps ::CZTop::Socket::REP
|
23
|
-
wraps ::CZTop::Socket::PAIR
|
24
|
-
wraps ::CZTop::Socket::ROUTER
|
25
|
-
wraps ::CZTop::Socket::DEALER
|
26
|
-
wraps ::CZTop::Socket::PUSH
|
27
|
-
wraps ::CZTop::Socket::PULL
|
28
|
-
wraps ::CZTop::Socket::PUB
|
29
|
-
wraps ::CZTop::Socket::SUB
|
30
|
-
wraps ::CZTop::Socket::XPUB
|
31
|
-
wraps ::CZTop::Socket::XSUB
|
32
|
-
|
33
|
-
|
34
|
-
# @see {CZTop::SendReceiveMethods#receive}
|
35
|
-
def receive
|
36
|
-
wait_readable
|
37
|
-
@io.receive
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
# @see {CZTop::SendReceiveMethods#<<}
|
42
|
-
def <<(...)
|
43
|
-
wait_writable
|
44
|
-
@io.<<(...)
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
# Waits for socket to become readable.
|
49
|
-
def wait_readable(timeout = read_timeout)
|
50
|
-
@io_fd ||= ::IO.for_fd @io.fd, autoclose: false
|
51
|
-
|
52
|
-
return true if @io.readable?
|
53
|
-
|
54
|
-
if timeout
|
55
|
-
timeout_at = now + timeout
|
56
|
-
|
57
|
-
while true
|
58
|
-
@io_fd.wait_readable(timeout)
|
59
|
-
break if @io.readable?
|
60
|
-
raise ::IO::TimeoutError if now >= timeout_at
|
61
|
-
end
|
62
|
-
else
|
63
|
-
@io_fd.wait_readable until @io.readable?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
# Waits for socket to become writable.
|
69
|
-
def wait_writable(timeout = write_timeout)
|
70
|
-
@io_fd ||= ::IO.for_fd @io.fd, autoclose: false
|
71
|
-
|
72
|
-
return true if @io.writable?
|
73
|
-
|
74
|
-
if timeout
|
75
|
-
timeout_at = now + timeout
|
76
|
-
|
77
|
-
while true
|
78
|
-
@io_fd.wait_writable(timeout)
|
79
|
-
break if @io.writable?
|
80
|
-
raise ::IO::TimeoutError if now >= timeout_at
|
81
|
-
end
|
82
|
-
else
|
83
|
-
@io_fd.wait_writable until @io.writable?
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
# @return [Float, nil] the timeout in seconds used by {IO#wait_readable}
|
89
|
-
def read_timeout
|
90
|
-
timeout = @io.options.rcvtimeo
|
91
|
-
|
92
|
-
if timeout <= 0
|
93
|
-
timeout = nil
|
94
|
-
else
|
95
|
-
timeout = timeout.to_f / 1000
|
96
|
-
end
|
97
|
-
|
98
|
-
timeout
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
# @return [Float, nil] the timeout in seconds used by {IO#wait_writable}
|
103
|
-
def write_timeout
|
104
|
-
timeout = @io.options.sndtimeo
|
105
|
-
|
106
|
-
if timeout <= 0
|
107
|
-
timeout = nil
|
108
|
-
else
|
109
|
-
timeout = timeout.to_f / 1000
|
110
|
-
end
|
111
|
-
|
112
|
-
timeout
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
|
119
|
-
def now
|
120
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
data/perf/README.md
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
# Performance Measurement
|
2
|
-
|
3
|
-
This directory contains simple performance measurement utilities:
|
4
|
-
|
5
|
-
- `inproc_lat.rb` measures the latency of the inproc transport
|
6
|
-
- `inproc_thru.rb` measures the throughput of the inproc transport
|
7
|
-
- `local_lat.rb` and `remote_lat.rb` measure the latency of other transports
|
8
|
-
- `local_thru.rb` and `remote_thru.rb` measure the throughput of other transports (TODO)
|
9
|
-
|
10
|
-
## Example Output
|
11
|
-
|
12
|
-
On my laptop, it currently looks something like this:
|
13
|
-
|
14
|
-
### Latency
|
15
|
-
|
16
|
-
over inproc, using 10k roundtrips of a repeatedly allocated 1kb message:
|
17
|
-
```
|
18
|
-
$ bundle exec ./inproc_lat_reqrep.rb 1_000 10_000
|
19
|
-
message size: 1000 [B]
|
20
|
-
roundtrip count: 10000
|
21
|
-
elapsed time: 0.469 [s]
|
22
|
-
average latency: 23.439 [us]<Paste>
|
23
|
-
```
|
24
|
-
|
25
|
-
over IPC, using 10k roundtrips of a repeatedly allocated 1kb message:
|
26
|
-
```
|
27
|
-
$ bundle exec ./local_lat.rb ipc:///tmp/cztop-perf 1000 1000 & ./remote_lat.rb ipc:///tmp/cztop-perf 1000 1000
|
28
|
-
[3] 58043
|
29
|
-
message size: 1000 [B]
|
30
|
-
roundtrip count: 1000
|
31
|
-
elapsed time: 0.091 [s]
|
32
|
-
average latency: 45.482 [us]
|
33
|
-
[3] 58043 done ./local_lat.rb ipc:///tmp/cztop-perf 1000 1000
|
34
|
-
```
|
35
|
-
|
36
|
-
over local TCP/IP stack, using 10k roundtrips of a repeatedly allocated
|
37
|
-
1kb message:
|
38
|
-
```
|
39
|
-
$ bundle exec ./local_lat.rb tcp://127.0.0.1:55667 1000 1000 & ./remote_lat.rb tcp://127.0.0.1:55667 1000 1000
|
40
|
-
[3] 58064
|
41
|
-
message size: 1000 [B]
|
42
|
-
roundtrip count: 1000
|
43
|
-
elapsed time: 0.123 [s]
|
44
|
-
average latency: 61.434 [us]
|
45
|
-
[3] 58064 done ./local_lat.rb tcp://127.0.0.1:55667 1000 1000
|
46
|
-
```
|
47
|
-
|
48
|
-
### Throughput
|
49
|
-
|
50
|
-
over inproc, with message sizes from 100 bytes to 100kb, 10,000 each:
|
51
|
-
|
52
|
-
```
|
53
|
-
$ bundle exec ./inproc_thru.rb 100 10_000
|
54
|
-
message size: 100 [B]
|
55
|
-
message count: 10000
|
56
|
-
elapsed time: 0.270 [s]
|
57
|
-
mean throughput: 37093 [msg/s]
|
58
|
-
mean throughput: 29.674 [Mb/s]
|
59
|
-
|
60
|
-
$ bundle exec ./inproc_thru.rb 1_000 10_000
|
61
|
-
message size: 1000 [B]
|
62
|
-
message count: 10000
|
63
|
-
elapsed time: 0.260 [s]
|
64
|
-
mean throughput: 38498 [msg/s]
|
65
|
-
mean throughput: 307.987 [Mb/s]
|
66
|
-
|
67
|
-
$ bundle exec ./inproc_thru.rb 10_000 10_000
|
68
|
-
message size: 10000 [B]
|
69
|
-
message count: 10000
|
70
|
-
elapsed time: 0.317 [s]
|
71
|
-
mean throughput: 31501 [msg/s]
|
72
|
-
mean throughput: 2520.102 [Mb/s]
|
73
|
-
|
74
|
-
$ bundle exec ./inproc_thru.rb 100_000 10_000
|
75
|
-
message size: 100000 [B]
|
76
|
-
message count: 10000
|
77
|
-
elapsed time: 0.906 [s]
|
78
|
-
mean throughput: 11034 [msg/s]
|
79
|
-
mean throughput: 8827.440 [Mb/s]
|
80
|
-
```
|
data/perf/inproc_lat.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require "cztop"
|
3
|
-
require "benchmark"
|
4
|
-
#require "ruby-prof"
|
5
|
-
|
6
|
-
if ARGV.size != 2
|
7
|
-
abort <<MSG
|
8
|
-
Usage: #{$0} <message-size> <roundtrip-count>
|
9
|
-
MSG
|
10
|
-
end
|
11
|
-
|
12
|
-
MSG_SIZE = Integer(ARGV[0]) # bytes
|
13
|
-
ROUNDTRIP_COUNT = Integer(ARGV[1]) # round trips
|
14
|
-
MSG = "X" * MSG_SIZE
|
15
|
-
|
16
|
-
Thread.new do
|
17
|
-
s = CZTop::Socket::PAIR.new("@inproc://perf")
|
18
|
-
s.signal
|
19
|
-
ROUNDTRIP_COUNT.times do
|
20
|
-
msg = s.receive
|
21
|
-
raise "wrong message size" if msg.content_size != MSG_SIZE
|
22
|
-
s << msg
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
s = CZTop::Socket::PAIR.new(">inproc://perf")
|
27
|
-
s.wait
|
28
|
-
|
29
|
-
#RubyProf.start
|
30
|
-
tms = Benchmark.measure do
|
31
|
-
ROUNDTRIP_COUNT.times do
|
32
|
-
s << MSG
|
33
|
-
msg = s.receive
|
34
|
-
raise "wrong message size" if msg.content_size != MSG_SIZE
|
35
|
-
end
|
36
|
-
end
|
37
|
-
#rubyprof_result = RubyProf.stop
|
38
|
-
|
39
|
-
elapsed = tms.real
|
40
|
-
latency = elapsed / (ROUNDTRIP_COUNT * 2) * 1_000_000
|
41
|
-
puts "message size: #{MSG_SIZE} [B]"
|
42
|
-
puts "roundtrip count: #{ROUNDTRIP_COUNT}"
|
43
|
-
puts "elapsed time: %.3f [s]" % elapsed
|
44
|
-
puts "average latency: %.3f [us]" % latency
|
45
|
-
|
46
|
-
# print a flat profile to text
|
47
|
-
#printer = RubyProf::FlatPrinter.new(rubyprof_result)
|
48
|
-
#printer.print(STDOUT)
|
49
|
-
|
data/perf/inproc_thru.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require "cztop"
|
3
|
-
require "benchmark"
|
4
|
-
|
5
|
-
if ARGV.size != 2
|
6
|
-
abort <<MSG
|
7
|
-
Usage: #{$0} <message-size> <message-count>
|
8
|
-
MSG
|
9
|
-
end
|
10
|
-
|
11
|
-
MSG_SIZE = Integer(ARGV[0]) # bytes
|
12
|
-
MSG_COUNT = Integer(ARGV[1]) # number of messages
|
13
|
-
MSG = "X" * MSG_SIZE
|
14
|
-
|
15
|
-
Thread.new do
|
16
|
-
s = CZTop::Socket::PAIR.new("@inproc://perf")
|
17
|
-
s.signal
|
18
|
-
MSG_COUNT.times do
|
19
|
-
msg = s.receive
|
20
|
-
raise "wrong message size" if msg.content_size != MSG_SIZE
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
s = CZTop::Socket::PAIR.new(">inproc://perf")
|
25
|
-
s.wait
|
26
|
-
|
27
|
-
tms = Benchmark.measure do
|
28
|
-
MSG_COUNT.times do
|
29
|
-
s << MSG
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
elapsed = tms.real
|
34
|
-
|
35
|
-
throughput = MSG_COUNT / elapsed
|
36
|
-
megabits = (throughput * MSG_SIZE * 8) / 1_000_000
|
37
|
-
|
38
|
-
puts "message size: #{MSG_SIZE} [B]"
|
39
|
-
puts "message count: #{MSG_COUNT}"
|
40
|
-
puts "elapsed time: %.3f [s]" % elapsed
|
41
|
-
puts "mean throughput: %d [msg/s]" % throughput
|
42
|
-
puts "mean throughput: %.3f [Mb/s]" % megabits
|
data/perf/local_lat.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require "cztop"
|
3
|
-
require "benchmark"
|
4
|
-
|
5
|
-
if ARGV.size != 3
|
6
|
-
abort <<MSG
|
7
|
-
Usage: #{$0} <bind-to> <message-size> <roundtrip-count>
|
8
|
-
MSG
|
9
|
-
end
|
10
|
-
|
11
|
-
ENDPOINT = ARGV[0]
|
12
|
-
MSG_SIZE = Integer(ARGV[1]) # bytes
|
13
|
-
ROUNDTRIP_COUNT = Integer(ARGV[2]) # round trips
|
14
|
-
MSG = "X" * MSG_SIZE
|
15
|
-
|
16
|
-
s = CZTop::Socket::REP.new(ENDPOINT)
|
17
|
-
|
18
|
-
# synchronize
|
19
|
-
s.wait
|
20
|
-
s.signal
|
21
|
-
|
22
|
-
tms = Benchmark.measure do
|
23
|
-
ROUNDTRIP_COUNT.times do
|
24
|
-
msg = s.receive
|
25
|
-
raise "wrong message size" if msg.content_size != MSG_SIZE
|
26
|
-
s << msg
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
elapsed = tms.real
|
31
|
-
latency = elapsed / (ROUNDTRIP_COUNT * 2) * 1_000_000
|
32
|
-
puts "message size: #{MSG_SIZE} [B]"
|
33
|
-
puts "roundtrip count: #{ROUNDTRIP_COUNT}"
|
34
|
-
puts "elapsed time: %.3f [s]" % elapsed
|
35
|
-
puts "average latency: %.3f [us]" % latency
|
data/perf/remote_lat.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require "cztop"
|
3
|
-
require "benchmark"
|
4
|
-
|
5
|
-
if ARGV.size != 3
|
6
|
-
abort <<MSG
|
7
|
-
Usage: #{$0} <connect-to> <message-size> <roundtrip-count>
|
8
|
-
MSG
|
9
|
-
end
|
10
|
-
|
11
|
-
ENDPOINT = ARGV[0]
|
12
|
-
MSG_SIZE = Integer(ARGV[1]) # bytes
|
13
|
-
ROUNDTRIP_COUNT = Integer(ARGV[2]) # round trips
|
14
|
-
MSG = "X" * MSG_SIZE
|
15
|
-
|
16
|
-
s = CZTop::Socket::REQ.new(ENDPOINT)
|
17
|
-
|
18
|
-
# synchronize
|
19
|
-
s.signal
|
20
|
-
s.wait
|
21
|
-
|
22
|
-
ROUNDTRIP_COUNT.times do
|
23
|
-
s << MSG
|
24
|
-
msg = s.receive
|
25
|
-
raise "wrong message size" if msg.content_size != MSG_SIZE
|
26
|
-
end
|