cztop 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,276 +0,0 @@
1
- # Taxi System
2
-
3
- Suppose you're running a taxi company. You have a set of taxi drivers
4
- working for you. You'd like to connect them to your central server, so they're
5
- ready to get service requests from customers who'd like to get picked up by a
6
- taxi from some place X. As soon as a customer sends his service request, the
7
- central server will send the closest taxi nearby that's available to the
8
- customer.
9
-
10
- Of course you want the communication between the broker and the taxi drivers to
11
- be secure, meaning you want encryption and authentication.
12
-
13
- You also want ping-pong heartbeating, as you want to have confidence you can
14
- get in touch with your taxi drivers any time you want. And if a service
15
- request can't be delivered to a particular taxi driver, you wanna know
16
- immediately.
17
-
18
- This solution is implemented using CLIENT/SERVER sockets and the CURVE
19
- security mechanism.
20
-
21
- ## Broker
22
-
23
- Here's a possible implementation of the broker. What you'll have to provide
24
- are the environment variables `BROKER_ADDRESS` (the public TCP endpoint),
25
- `BROKER_CERT` (path to the broker's secret+public keys), and `CLIENT_CERTS`
26
- (directory to taxi drivers' certificates, public keys only).
27
-
28
- After the start, the broker will just start listening for the drivers (CLIENT
29
- sockets) to connect. After a driver has connected, authenticated, and sent its
30
- `HELLO` message, the broker answers with a `WELCOME` or `WELCOMEBACK` message,
31
- depending if the driver was connected before (it might have reconnected and
32
- been assigned a new routing ID).
33
-
34
- The broker will present you with a Pry shell. Right before starting the shell,
35
- there's a small usage information, but it's not very well visible due to Pry's
36
- noisy start. It's simple, though. Inside that shell, you can use the method
37
- `#send_command(driver, command)`. Example:
38
-
39
- ```
40
- pry> send_command("driver1", "foobar")
41
- ```
42
-
43
- Depending on whether the driver is connected, it'll send the message or report
44
- that it cannot do so.
45
-
46
- ```ruby
47
- #!/usr/bin/env ruby
48
- require 'pry'
49
- require 'pathname'
50
- require 'cztop'
51
-
52
- endpoint = ENV["BROKER_ADDRESS"]
53
- broker_cert = CZTop::Certificate.load ENV["BROKER_CERT"] # secret+public
54
- client_certs = ENV["CLIENT_CERTS"] # /path/to/client_certs/
55
- drivers = Pathname.new(client_certs).children.map(&:basename).map(&:to_s)
56
-
57
- authenticator = CZTop::Authenticator.new
58
- authenticator.verbose!
59
- authenticator.curve(client_certs)
60
-
61
- # create and bind socket
62
- @socket = CZTop::Socket::SERVER.new
63
- @socket.CURVE_server!(broker_cert)
64
- #socket.options.sndtimeo = 0
65
- @socket.options.heartbeat_ivl = 100#ms
66
- @socket.options.heartbeat_timeout = 300#ms
67
- @socket.bind(endpoint)
68
-
69
- puts ">>> Socket bound to #{endpoint.inspect}"
70
-
71
- # get and print socket events
72
- Thread.new do
73
- monitor = CZTop::Monitor.new(@socket)
74
- monitor.listen("ALL")
75
- monitor.start
76
- while msg = monitor.next
77
- puts ">>> Socket event: #{msg.inspect}"
78
- end
79
- end
80
-
81
- # receive messages from drivers
82
- @driver_map = {} # driver name => routing ID
83
- Thread.new do
84
-
85
- # CZTop::Loop (zloop) doesn't work with SERVER sockets :(
86
- poller = CZTop::Poller.new(@socket)
87
- while true
88
- puts "waiting for socket to become readable ..."
89
- socket = poller.wait
90
- puts "socket is readable"
91
- msg = socket.receive
92
- puts "got message"
93
- command, argument = msg[0].split("\t", 2)
94
-
95
- case command
96
- when "HELLO"
97
- driver = argument
98
- puts ">>> Driver #{driver.inspect} has connected."
99
- welcome = @driver_map.key?(driver) ? "WELCOMEBACK" : "WELCOME"
100
-
101
- # remember driver's assigned message routing ID
102
- @driver_map[driver] = msg.routing_id
103
-
104
- # send WELCOME or WELCOMEBACK
105
- rep = CZTop::Message.new(welcome)
106
- rep.routing_id = @driver_map[driver]
107
- socket << rep
108
- puts ">>> Sent #{welcome.inspect} to #{driver.inspect}"
109
- end
110
- end
111
- end
112
-
113
- def send_command(driver, command)
114
- if command.nil? || command.empty?
115
- puts "!!! No message given."
116
- return
117
- end
118
- if not @driver_map.key?(driver)
119
- puts "!!! Driver #{driver.inspect} has never connected."
120
- return
121
- end
122
- puts ">>> Sending message to #{driver.inspect} ..."
123
- msg = CZTop::Message.new(command)
124
- msg.routing_id = @driver_map[driver]
125
- @socket << msg
126
- rescue SocketError
127
- puts "!!! Driver #{driver.inspect} isn't connected anymore."
128
- end
129
-
130
- ##
131
- # REPL for user to play
132
- #
133
- puts <<MSG
134
- You can now send messages to the drivers yourself.
135
- The use the method #send_command, like this:
136
-
137
- pry> send_command("driver1", "PICKUP\t(8.541694,47.376887)")
138
-
139
- This should show something like this in the client.rb terminal:
140
-
141
- 03:17:01 driver1.1 | received message: "PICKUP\t(8.541694,47.376887)"
142
- MSG
143
-
144
- binding.pry
145
- ```
146
-
147
- ## Client
148
-
149
- Here you have to provide the environment variables `BROKER_ADDRESS` (ditto),
150
- `BROKER_CERT` (public key only), `CLIENT_CERT` (taxi driver's certificate
151
- containing the secret+public keys).
152
-
153
- After connecting to the broker and completing the security handshake, the
154
- client sends a `HELLO` message, after which it immediately expects some answer
155
- from the broker (see above). After that, it just listens for messages (service
156
- requests) and prints them into the terminal.
157
-
158
- ```ruby
159
- #!/usr/bin/env ruby
160
- require 'cztop'
161
-
162
- endpoint = ENV["BROKER_ADDRESS"]
163
- broker_cert = CZTop::Certificate.load ENV["BROKER_CERT"] # public only
164
- client_cert = CZTop::Certificate.load ENV["CLIENT_CERT"]
165
-
166
- @socket = CZTop::Socket::CLIENT.new
167
- @socket.CURVE_client!(client_cert, broker_cert)
168
- @socket.options.sndtimeo = 2000#ms
169
-
170
- # heartbeating:
171
- # * send PING every 100ms
172
- # * close connection after 300ms of no life sign from broker
173
- # * tell broker to close connection after 500ms of no life sign from client
174
- @socket.options.heartbeat_ivl = 100#ms
175
- @socket.options.heartbeat_timeout = 300#ms
176
- @socket.options.heartbeat_ttl = 500#ms
177
-
178
- @socket.connect(endpoint)
179
- puts ">>> connected."
180
-
181
- # tell broker who we are
182
- @socket << "HELLO\t#{client_cert["driver_name"]}"
183
- puts ">>> sent HELLO."
184
- welcome = @socket.receive[0]
185
- puts ">>> got #{welcome}."
186
-
187
- poller = CZTop::Poller.new(@socket)
188
- while true
189
- socket = poller.wait
190
- message = socket.receive
191
- puts ">>> received message: #{message[0].inspect}"
192
- end
193
- ```
194
-
195
- ## How to run the example
196
-
197
- ### Generate broker's and drivers' keys
198
-
199
- Here's a simple script that'll create the broker's certificate and the taxi
200
- drivers' certificates. There are also public key only files so a minimum amount
201
- of information can be made available on one system, e.g. a taxi driver's system
202
- must not know the broker's secret key. Also, the broker doesn't necessarily
203
- need to know the clients' secret keys just to authenticate them.
204
-
205
- ```ruby
206
- #!/usr/bin/env ruby
207
- require 'cztop'
208
- require 'fileutils'
209
- FileUtils.cd(File.dirname(__FILE__))
210
- FileUtils.mkdir "public_keys"
211
- FileUtils.mkdir "public_keys/drivers"
212
- FileUtils.mkdir "secret_keys"
213
- FileUtils.mkdir "secret_keys/drivers"
214
- #FileUtils.mkdir "certs/drivers"
215
-
216
- DRIVERS = %w[ driver1 driver2 driver3 ]
217
-
218
- # broker certificate
219
- cert = CZTop::Certificate.new
220
- cert.save("secret_keys/broker")
221
- cert.save_public("public_keys/broker")
222
-
223
- # driver certificates
224
- DRIVERS.each do |driver_name|
225
- cert = CZTop::Certificate.new
226
- cert["driver_name"] = driver_name
227
- cert.save "secret_keys/drivers/#{driver_name}"
228
- cert.save_public "public_keys/drivers/#{driver_name}"
229
- end
230
-
231
- ```
232
- Run it as follows:
233
-
234
- ```
235
- ./generate_keys.rb
236
- ```
237
-
238
- ### Start broker
239
-
240
- Run this:
241
-
242
- ```
243
- ./start_broker.sh
244
- ```
245
-
246
- which will execute the following script:
247
-
248
- ```sh
249
- #!/bin/sh -x
250
- BROKER_ADDRESS=tcp://127.0.0.1:4455 BROKER_CERT=secret_keys/broker CLIENT_CERTS=public_keys/drivers ./broker.rb
251
- ```
252
-
253
- ### Start driver software instances
254
-
255
- Run this in another terminal:
256
-
257
- ```
258
- ./start_clients.sh
259
- ```
260
-
261
- which will execute the following script:
262
-
263
- ```sh
264
- #!/bin/sh -x
265
- export BROKER_ADDRESS=tcp://127.0.0.1:4455
266
- export BROKER_CERT=public_keys/broker
267
- CLIENT_CERT=secret_keys/drivers/driver1_secret ./client.rb &
268
- CLIENT_CERT=secret_keys/drivers/driver2_secret ./client.rb &
269
- CLIENT_CERT=secret_keys/drivers/driver3_secret ./client.rb &
270
- jobs
271
- jobs -p
272
- jobs -l
273
- trap 'kill $(jobs -p)' EXIT
274
- wait
275
- ```
276
-
@@ -1,97 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'pry'
3
- require 'pathname'
4
- require 'cztop'
5
-
6
- endpoint = ENV["BROKER_ADDRESS"]
7
- broker_cert = CZTop::Certificate.load ENV["BROKER_CERT"] # secret+public
8
- client_certs = ENV["CLIENT_CERTS"] # /path/to/client_certs/
9
- drivers = Pathname.new(client_certs).children.map(&:basename).map(&:to_s)
10
-
11
- authenticator = CZTop::Authenticator.new
12
- authenticator.verbose!
13
- authenticator.curve(client_certs)
14
-
15
- # create and bind socket
16
- @socket = CZTop::Socket::SERVER.new
17
- @socket.CURVE_server!(broker_cert)
18
- #socket.options.sndtimeo = 0
19
- @socket.options.heartbeat_ivl = 100#ms
20
- @socket.options.heartbeat_timeout = 300#ms
21
- @socket.bind(endpoint)
22
-
23
- puts ">>> Socket bound to #{endpoint.inspect}"
24
-
25
- # get and print socket events
26
- Thread.new do
27
- monitor = CZTop::Monitor.new(@socket)
28
- monitor.listen("ALL")
29
- monitor.start
30
- while msg = monitor.next
31
- puts ">>> Socket event: #{msg.inspect}"
32
- end
33
- end
34
-
35
- # receive messages from drivers
36
- @driver_map = {} # driver name => routing ID
37
- Thread.new do
38
-
39
- poller = CZTop::Poller.new(@socket)
40
- while true
41
- puts "waiting for socket to become readable ..."
42
- socket = poller.simple_wait
43
- puts "socket is readable"
44
- msg = socket.receive
45
- puts "got message"
46
- command, argument = msg[0].split("\t", 2)
47
-
48
- case command
49
- when "HELLO"
50
- driver = argument
51
- puts ">>> Driver #{driver.inspect} has connected."
52
- welcome = @driver_map.key?(driver) ? "WELCOMEBACK" : "WELCOME"
53
-
54
- # remember driver's assigned message routing ID
55
- @driver_map[driver] = msg.routing_id
56
-
57
- # send WELCOME or WELCOMEBACK
58
- rep = CZTop::Message.new(welcome)
59
- rep.routing_id = @driver_map[driver]
60
- socket << rep
61
- puts ">>> Sent #{welcome.inspect} to #{driver.inspect}"
62
- end
63
- end
64
- end
65
-
66
- def send_command(driver, command)
67
- if command.nil? || command.empty?
68
- puts "!!! No message given."
69
- return
70
- end
71
- if not @driver_map.key?(driver)
72
- puts "!!! Driver #{driver.inspect} has never connected."
73
- return
74
- end
75
- puts ">>> Sending message to #{driver.inspect} ..."
76
- msg = CZTop::Message.new(command)
77
- msg.routing_id = @driver_map[driver]
78
- @socket << msg
79
- rescue SocketError
80
- puts "!!! Driver #{driver.inspect} isn't connected anymore."
81
- end
82
-
83
- ##
84
- # REPL for user to play
85
- #
86
- puts <<MSG
87
- You can now send messages to the drivers yourself.
88
- The use the method #send_command, like this:
89
-
90
- pry> send_command("driver1", "PICKUP\t(8.541694,47.376887)")
91
-
92
- This should show something like this in the client.rb terminal:
93
-
94
- 03:17:01 driver1.1 | received message: "PICKUP\t(8.541694,47.376887)"
95
- MSG
96
-
97
- binding.pry
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'cztop'
3
-
4
- endpoint = ENV["BROKER_ADDRESS"]
5
- broker_cert = CZTop::Certificate.load ENV["BROKER_CERT"] # public only
6
- client_cert = CZTop::Certificate.load ENV["CLIENT_CERT"]
7
-
8
- @socket = CZTop::Socket::CLIENT.new
9
- @socket.CURVE_client!(client_cert, broker_cert)
10
- @socket.options.sndtimeo = 2000#ms
11
-
12
- # heartbeating:
13
- # * send PING every 100ms
14
- # * close connection after 300ms of no life sign from broker
15
- # * tell broker to close connection after 500ms of no life sign from client
16
- @socket.options.heartbeat_ivl = 100#ms
17
- @socket.options.heartbeat_timeout = 300#ms
18
- @socket.options.heartbeat_ttl = 500#ms
19
-
20
- @socket.connect(endpoint)
21
- puts ">>> connected."
22
-
23
- # tell broker who we are
24
- @socket << "HELLO\t#{client_cert["driver_name"]}"
25
- puts ">>> sent HELLO."
26
- welcome = @socket.receive[0]
27
- puts ">>> got #{welcome}."
28
-
29
- poller = CZTop::Poller.new(@socket)
30
- while true
31
- socket = poller.simple_wait
32
- message = socket.receive
33
- puts ">>> received message: #{message[0].inspect}"
34
- end
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'cztop'
3
- require 'fileutils'
4
- FileUtils.cd(File.dirname(__FILE__))
5
- FileUtils.mkdir "public_keys"
6
- FileUtils.mkdir "public_keys/drivers"
7
- FileUtils.mkdir "secret_keys"
8
- FileUtils.mkdir "secret_keys/drivers"
9
- #FileUtils.mkdir "certs/drivers"
10
-
11
- DRIVERS = %w[ driver1 driver2 driver3 ]
12
-
13
- # broker certificate
14
- cert = CZTop::Certificate.new
15
- cert.save("secret_keys/broker")
16
- cert.save_public("public_keys/broker")
17
-
18
- # driver certificates
19
- DRIVERS.each do |driver_name|
20
- cert = CZTop::Certificate.new
21
- cert["driver_name"] = driver_name
22
- cert.save "secret_keys/drivers/#{driver_name}"
23
- cert.save_public "public_keys/drivers/#{driver_name}"
24
- end
@@ -1,2 +0,0 @@
1
- #!/bin/sh -x
2
- BROKER_ADDRESS=tcp://127.0.0.1:4455 BROKER_CERT=secret_keys/broker CLIENT_CERTS=public_keys/drivers ./broker.rb
@@ -1,11 +0,0 @@
1
- #!/bin/sh -x
2
- export BROKER_ADDRESS=tcp://127.0.0.1:4455
3
- export BROKER_CERT=public_keys/broker
4
- CLIENT_CERT=secret_keys/drivers/driver1_secret ./client.rb &
5
- CLIENT_CERT=secret_keys/drivers/driver2_secret ./client.rb &
6
- CLIENT_CERT=secret_keys/drivers/driver3_secret ./client.rb &
7
- jobs
8
- jobs -p
9
- jobs -l
10
- trap 'kill $(jobs -p)' EXIT
11
- wait
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Weather update server, based on ZMQ's zguide.
4
- # Binds PUB socket to ipc:///tmp/weather_pubsub_example
5
- # Publishes random weather updates
6
- #
7
-
8
- require 'cztop'
9
-
10
- # create and bind socket
11
- socket = CZTop::Socket::PUB.new("ipc:///tmp/weather_pubsub_example")
12
- puts "<<< Socket bound to #{socket.last_endpoint.inspect}"
13
-
14
- while true
15
- # Generate values for zipcodes
16
- zipcode = rand(100000)
17
- temperature = rand(215) - 80
18
- relhumidity = rand(50) + 10
19
-
20
- update = "%05d %d %d" % [zipcode, temperature, relhumidity]
21
- puts update
22
-
23
- socket << update
24
- end
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Weather update client, based on that from ZMQ's zguide.
4
- # Connects SUB socket to ipc:///tmp/weather_pubsub_example
5
- # Collects weather updates and finds avg temp in zipcode
6
- #
7
-
8
- require 'cztop'
9
-
10
- COUNT = 100
11
-
12
- # Create socket, connect to publisher.
13
- socket = CZTop::Socket::SUB.new("ipc:///tmp/weather_pubsub_example")
14
- puts ">>> Socket Connected"
15
-
16
- # Subscribe to zipcode. Default: Chicago - 60606
17
- filter = ARGV.size > 0 ? ARGV[0] : "60606"
18
- socket.subscribe(filter)
19
-
20
- # gather & process COUNT updates.
21
- print "Gathering #{COUNT} samples."
22
- total_temp = 0
23
- 1.upto(COUNT) do |update_nbr|
24
- msg = socket.receive
25
-
26
- zipcode, temperature, relhumidity = msg[0].split.map(&:to_i)
27
- total_temp += temperature
28
- # just to show that we're doing something...
29
- print "." if update_nbr % 5 == 0
30
- end
31
- print "\n"
32
-
33
- puts "Average temperatuer for zipcode #{filter} was #{total_temp / COUNT}F."
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