pbenchmark 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []