pbenchmark 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +48 -0
- data/bin/pbenchmark +182 -0
- metadata +103 -0
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# pbenchmark
|
2
|
+
|
3
|
+
A simple tool to benchmark Pusher.com compatible servers.
|
4
|
+
|
5
|
+
[![Dependency Status][2]][1]
|
6
|
+
|
7
|
+
[1]: https://gemnasium.com/tech-angels/pb
|
8
|
+
[2]: https://gemnasium.com/tech-angels/pb.png
|
9
|
+
|
10
|
+
## Getting started
|
11
|
+
|
12
|
+
Install the pbenchmark gem:
|
13
|
+
|
14
|
+
gem install pbenchmark
|
15
|
+
|
16
|
+
Run it against your server, for example a Slanger daemon:
|
17
|
+
|
18
|
+
pbenchmark -c 10 -n 5 -i 43 -k bcff8137f9c04db491199d4578a37286 -s 68f5400d1aaa4d1bbaaf70bb0b866cb7 -a 127.0.0.1:80 -w 127.0.0.1:8080
|
19
|
+
|
20
|
+
Messages are sent via the API, and the time it took them to reach the websocket clients is printed.
|
21
|
+
|
22
|
+
## Commmand line parameters
|
23
|
+
|
24
|
+
<pre>
|
25
|
+
-c Number of websocket clients.
|
26
|
+
|
27
|
+
-n Number of messages to send via the API.
|
28
|
+
|
29
|
+
-i Application ID.
|
30
|
+
|
31
|
+
-k Application key.
|
32
|
+
|
33
|
+
-s Application secret.
|
34
|
+
|
35
|
+
-a API host and port. Example: 127.0.0.1:80.
|
36
|
+
|
37
|
+
-w Websocket server host and port. Example: 127.0.0.1:8080
|
38
|
+
|
39
|
+
--size Payload size in bytes.
|
40
|
+
</pre>
|
41
|
+
|
42
|
+
## Credits
|
43
|
+
|
44
|
+
Gilbert Roulot @ Tech-angels - http://www.tech-angels.com/
|
45
|
+
|
46
|
+
[](http://www.tech-angels.com)
|
47
|
+
|
48
|
+
|
data/bin/pbenchmark
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright (c)2012 Tech-Angels
|
4
|
+
#
|
5
|
+
# This file is part of PBenchmark.
|
6
|
+
#
|
7
|
+
# PBenchmark is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# PBenchmark is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with PBenchmark. If not, see <http://www.gnu.org/licenses/>. 2
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler'
|
23
|
+
require 'active_support/json'
|
24
|
+
require 'eventmachine'
|
25
|
+
require 'em-websocket-client'
|
26
|
+
require 'pusher'
|
27
|
+
require 'optparse'
|
28
|
+
|
29
|
+
module PBenchmark
|
30
|
+
@all_latencies = []
|
31
|
+
def get_latencies
|
32
|
+
@all_latencies
|
33
|
+
end
|
34
|
+
|
35
|
+
@options = {
|
36
|
+
api_host: '127.0.0.1',
|
37
|
+
api_port: '4567',
|
38
|
+
websocket_host: '127.0.0.1',
|
39
|
+
websocket_port: '8080', debug: false,
|
40
|
+
nb_clients: 1,
|
41
|
+
nb_messages: 10,
|
42
|
+
payload_size: 100,
|
43
|
+
}
|
44
|
+
@opts_app_id = nil
|
45
|
+
@opts_app_key = nil
|
46
|
+
@opts_secret = nil
|
47
|
+
|
48
|
+
OptionParser.new do |opts|
|
49
|
+
opts.on '-c', '--concurrency NUMBER', 'Number of clients' do |k|
|
50
|
+
@options[:nb_clients] = k.to_i
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on '-n', '--messages NUMBER', 'Number of messages' do |k|
|
54
|
+
@options[:nb_messages] = k.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on '-i', '--app_id APP_ID', "Pusher application id" do |k|
|
58
|
+
@opts_app_id = k
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on '-k', '--app_key APP_KEY', "Pusher application key" do |k|
|
62
|
+
@opts_app_key = k
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on '-s', '--secret SECRET', "Pusher application secret" do |k|
|
66
|
+
@opts_secret = k
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on '-a', '--api_host HOST', "API service address (Default: 0.0.0.0:4567)" do |p|
|
70
|
+
@options[:api_host], @options[:api_port] = p.split(':')
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on '-w', '--websocket_host HOST', "WebSocket service address (Default: 0.0.0.0:8080)" do |p|
|
74
|
+
@options[:websocket_host], @options[:websocket_port] = p.split(':')
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on '--size NUMBER', 'Payload size in bytes. (Default: 100)' do |s|
|
78
|
+
@options[:payload_size] = s.to_i
|
79
|
+
end
|
80
|
+
end.parse!
|
81
|
+
|
82
|
+
def new_websocket
|
83
|
+
EM::WebSocketClient.connect("ws://" + @options[:websocket_host] + ":" + @options[:websocket_port] + "/app/" + @opts_app_key + "?client=js&version=1.8.5")
|
84
|
+
end
|
85
|
+
|
86
|
+
def configure_pusher
|
87
|
+
Pusher.tap do |p|
|
88
|
+
p.host = @options[:api_host]
|
89
|
+
p.port = @options[:api_port].to_i
|
90
|
+
p.app_id = @opts_app_id
|
91
|
+
p.secret = @opts_secret
|
92
|
+
p.key = @opts_app_key
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_stats(latencies)
|
97
|
+
lowest = latencies.min * 1000
|
98
|
+
highest = latencies.max * 1000
|
99
|
+
total = latencies.inject(:+) * 1000
|
100
|
+
len = latencies.length
|
101
|
+
average = total.to_f / len
|
102
|
+
sorted = latencies.sort
|
103
|
+
median = (len % 2 == 1 ? sorted[len/2] : (sorted[len / 2 - 1] + sorted[len / 2]).to_f / 2) * 1000
|
104
|
+
return {
|
105
|
+
min: lowest,
|
106
|
+
mean: average,
|
107
|
+
median: median,
|
108
|
+
max: highest
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def regular_channel
|
113
|
+
configure_pusher
|
114
|
+
latencies = []
|
115
|
+
client_who_received = 0
|
116
|
+
messages_to_send = @options[:nb_messages].to_i
|
117
|
+
puts "Latency (ms)"
|
118
|
+
puts "min\tmean\tmedian\tmax"
|
119
|
+
|
120
|
+
EM.run do
|
121
|
+
# Connect clients
|
122
|
+
(1..@options[:nb_clients]).each do
|
123
|
+
websocket = new_websocket
|
124
|
+
|
125
|
+
websocket.errback { |e|
|
126
|
+
puts "Websocket error: " + e.to_s
|
127
|
+
EM.stop
|
128
|
+
}
|
129
|
+
|
130
|
+
websocket.stream do |message|
|
131
|
+
now = Time.now.to_f
|
132
|
+
message = JSON.parse(message)
|
133
|
+
data = message['data']
|
134
|
+
data = JSON.parse(data) unless data.is_a?(Hash)
|
135
|
+
if data.has_key?('time')
|
136
|
+
latency = now - data['time']
|
137
|
+
latencies << latency
|
138
|
+
client_who_received += 1
|
139
|
+
end
|
140
|
+
if client_who_received >= @options[:nb_clients] then
|
141
|
+
# Display statistics
|
142
|
+
stats = get_stats(latencies)
|
143
|
+
puts "%.2f\t%.2f\t%.2f\t%.2f" % [stats[:min], stats[:mean], stats[:median], stats[:max]]
|
144
|
+
@all_latencies += latencies
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
websocket.callback do
|
149
|
+
websocket.send_msg({ event: 'pusher:subscribe', data: { channel: 'MY_CHANNEL'} }.to_json)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
# Send messages to the channel
|
154
|
+
EM::PeriodicTimer.new(1) do
|
155
|
+
if messages_to_send > 0
|
156
|
+
client_who_received = 0
|
157
|
+
latencies = []
|
158
|
+
Pusher['MY_CHANNEL'].trigger_async 'an_event', { time: Time.now.to_f, payload: " " * @options[:payload_size] }
|
159
|
+
messages_to_send -= 1
|
160
|
+
else
|
161
|
+
EM.stop
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
extend self
|
168
|
+
end
|
169
|
+
|
170
|
+
begin
|
171
|
+
PBenchmark.regular_channel
|
172
|
+
rescue SystemExit, Interrupt
|
173
|
+
end
|
174
|
+
|
175
|
+
# Print final stats
|
176
|
+
stats = PBenchmark.get_stats(PBenchmark.get_latencies)
|
177
|
+
puts "\n\nOverall latencies (ms)"
|
178
|
+
puts "min\tmean\tmedian\tmax"
|
179
|
+
puts "%.2f\t%.2f\t%.2f\t%.2f" % [stats[:min], stats[:mean], stats[:median], stats[:max]]
|
180
|
+
|
181
|
+
|
182
|
+
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pbenchmark
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Gilbert Roulot
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &6043060 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *6043060
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: eventmachine
|
27
|
+
requirement: &6040680 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *6040680
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: em-http-request
|
38
|
+
requirement: &5286240 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.3
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *5286240
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: em-websocket-client
|
49
|
+
requirement: &5284560 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.1
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *5284560
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: pusher
|
60
|
+
requirement: &5283720 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.8.2
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *5283720
|
69
|
+
description: A benchmarking tool for servers compatible with the Pusher protocol.
|
70
|
+
email: gilbert.roulot@tech-angels.com
|
71
|
+
executables:
|
72
|
+
- pbenchmark
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.md
|
77
|
+
- bin/pbenchmark
|
78
|
+
homepage: https://github.com/tech-angels/pbenchmark
|
79
|
+
licenses:
|
80
|
+
- GPL-3
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- .
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.9.3
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 1.8.10
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: A benchmarking tool for servers compatible with the Pusher protocol.
|
103
|
+
test_files: []
|