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.
Files changed (3) hide show
  1. data/README.md +48 -0
  2. data/bin/pbenchmark +182 -0
  3. metadata +103 -0
@@ -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
+ [![Tech-Angels](http://media.tumblr.com/tumblr_m5ay3bQiER1qa44ov.png)](http://www.tech-angels.com)
47
+
48
+
@@ -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: []