grockit-thin 0.8.2

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 (136) hide show
  1. data/CHANGELOG +220 -0
  2. data/COMMITTERS +3 -0
  3. data/COPYING +18 -0
  4. data/README +77 -0
  5. data/Rakefile +13 -0
  6. data/benchmark/abc +51 -0
  7. data/benchmark/benchmarker.rb +80 -0
  8. data/benchmark/runner +79 -0
  9. data/bin/thin +6 -0
  10. data/example/adapter.rb +32 -0
  11. data/example/config.ru +23 -0
  12. data/example/monit_sockets +20 -0
  13. data/example/monit_unixsock +20 -0
  14. data/example/myapp.rb +1 -0
  15. data/example/ramaze.ru +12 -0
  16. data/example/thin.god +80 -0
  17. data/example/thin_solaris_smf.erb +36 -0
  18. data/example/thin_solaris_smf.readme.txt +150 -0
  19. data/example/vlad.rake +61 -0
  20. data/ext/thin_parser/common.rl +55 -0
  21. data/ext/thin_parser/ext_help.h +14 -0
  22. data/ext/thin_parser/extconf.rb +6 -0
  23. data/ext/thin_parser/parser.c +1218 -0
  24. data/ext/thin_parser/parser.h +49 -0
  25. data/ext/thin_parser/parser.rl +159 -0
  26. data/ext/thin_parser/thin.c +433 -0
  27. data/lib/rack/adapter/loader.rb +78 -0
  28. data/lib/rack/adapter/rails.rb +167 -0
  29. data/lib/rack/handler/thin.rb +18 -0
  30. data/lib/thin.rb +49 -0
  31. data/lib/thin/backends/base.rb +135 -0
  32. data/lib/thin/backends/swiftiply_client.rb +56 -0
  33. data/lib/thin/backends/tcp_server.rb +29 -0
  34. data/lib/thin/backends/unix_server.rb +51 -0
  35. data/lib/thin/command.rb +52 -0
  36. data/lib/thin/connection.rb +178 -0
  37. data/lib/thin/controllers/cluster.rb +121 -0
  38. data/lib/thin/controllers/controller.rb +182 -0
  39. data/lib/thin/controllers/service.rb +75 -0
  40. data/lib/thin/controllers/service.sh.erb +39 -0
  41. data/lib/thin/daemonizing.rb +163 -0
  42. data/lib/thin/headers.rb +31 -0
  43. data/lib/thin/logging.rb +54 -0
  44. data/lib/thin/request.rb +144 -0
  45. data/lib/thin/response.rb +96 -0
  46. data/lib/thin/runner.rb +208 -0
  47. data/lib/thin/server.rb +241 -0
  48. data/lib/thin/stats.html.erb +216 -0
  49. data/lib/thin/stats.rb +52 -0
  50. data/lib/thin/statuses.rb +43 -0
  51. data/lib/thin/version.rb +32 -0
  52. data/spec/backends/swiftiply_client_spec.rb +66 -0
  53. data/spec/backends/tcp_server_spec.rb +33 -0
  54. data/spec/backends/unix_server_spec.rb +37 -0
  55. data/spec/command_spec.rb +20 -0
  56. data/spec/configs/cluster.yml +9 -0
  57. data/spec/configs/single.yml +9 -0
  58. data/spec/connection_spec.rb +105 -0
  59. data/spec/controllers/cluster_spec.rb +179 -0
  60. data/spec/controllers/controller_spec.rb +121 -0
  61. data/spec/controllers/service_spec.rb +50 -0
  62. data/spec/daemonizing_spec.rb +192 -0
  63. data/spec/headers_spec.rb +29 -0
  64. data/spec/logging_spec.rb +46 -0
  65. data/spec/perf/request_perf_spec.rb +50 -0
  66. data/spec/perf/response_perf_spec.rb +19 -0
  67. data/spec/perf/server_perf_spec.rb +39 -0
  68. data/spec/rack/loader_spec.rb +29 -0
  69. data/spec/rack/rails_adapter_spec.rb +106 -0
  70. data/spec/rails_app/app/controllers/application.rb +10 -0
  71. data/spec/rails_app/app/controllers/simple_controller.rb +19 -0
  72. data/spec/rails_app/app/helpers/application_helper.rb +3 -0
  73. data/spec/rails_app/app/views/simple/index.html.erb +15 -0
  74. data/spec/rails_app/config/boot.rb +109 -0
  75. data/spec/rails_app/config/environment.rb +64 -0
  76. data/spec/rails_app/config/environments/development.rb +18 -0
  77. data/spec/rails_app/config/environments/production.rb +19 -0
  78. data/spec/rails_app/config/environments/test.rb +22 -0
  79. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  80. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  81. data/spec/rails_app/config/routes.rb +35 -0
  82. data/spec/rails_app/public/404.html +30 -0
  83. data/spec/rails_app/public/422.html +30 -0
  84. data/spec/rails_app/public/500.html +30 -0
  85. data/spec/rails_app/public/dispatch.cgi +10 -0
  86. data/spec/rails_app/public/dispatch.fcgi +24 -0
  87. data/spec/rails_app/public/dispatch.rb +10 -0
  88. data/spec/rails_app/public/favicon.ico +0 -0
  89. data/spec/rails_app/public/images/rails.png +0 -0
  90. data/spec/rails_app/public/index.html +277 -0
  91. data/spec/rails_app/public/javascripts/application.js +2 -0
  92. data/spec/rails_app/public/javascripts/controls.js +963 -0
  93. data/spec/rails_app/public/javascripts/dragdrop.js +972 -0
  94. data/spec/rails_app/public/javascripts/effects.js +1120 -0
  95. data/spec/rails_app/public/javascripts/prototype.js +4225 -0
  96. data/spec/rails_app/public/robots.txt +5 -0
  97. data/spec/rails_app/script/about +3 -0
  98. data/spec/rails_app/script/console +3 -0
  99. data/spec/rails_app/script/destroy +3 -0
  100. data/spec/rails_app/script/generate +3 -0
  101. data/spec/rails_app/script/performance/benchmarker +3 -0
  102. data/spec/rails_app/script/performance/profiler +3 -0
  103. data/spec/rails_app/script/performance/request +3 -0
  104. data/spec/rails_app/script/plugin +3 -0
  105. data/spec/rails_app/script/process/inspector +3 -0
  106. data/spec/rails_app/script/process/reaper +3 -0
  107. data/spec/rails_app/script/process/spawner +3 -0
  108. data/spec/rails_app/script/runner +3 -0
  109. data/spec/rails_app/script/server +3 -0
  110. data/spec/request/mongrel_spec.rb +39 -0
  111. data/spec/request/parser_spec.rb +191 -0
  112. data/spec/request/persistent_spec.rb +35 -0
  113. data/spec/request/processing_spec.rb +45 -0
  114. data/spec/response_spec.rb +76 -0
  115. data/spec/runner_spec.rb +167 -0
  116. data/spec/server/builder_spec.rb +44 -0
  117. data/spec/server/pipelining_spec.rb +109 -0
  118. data/spec/server/robustness_spec.rb +34 -0
  119. data/spec/server/stopping_spec.rb +45 -0
  120. data/spec/server/swiftiply.yml +6 -0
  121. data/spec/server/swiftiply_spec.rb +32 -0
  122. data/spec/server/tcp_spec.rb +57 -0
  123. data/spec/server/threaded_spec.rb +27 -0
  124. data/spec/server/unix_socket_spec.rb +26 -0
  125. data/spec/server_spec.rb +96 -0
  126. data/spec/spec_helper.rb +219 -0
  127. data/tasks/announce.rake +22 -0
  128. data/tasks/deploy.rake +16 -0
  129. data/tasks/email.erb +30 -0
  130. data/tasks/ext.rake +42 -0
  131. data/tasks/gem.rake +102 -0
  132. data/tasks/rdoc.rake +25 -0
  133. data/tasks/site.rake +15 -0
  134. data/tasks/spec.rake +48 -0
  135. data/tasks/stats.rake +28 -0
  136. metadata +240 -0
data/CHANGELOG ADDED
@@ -0,0 +1,220 @@
1
+ == 1.0.0 The Big release
2
+ * Add Content-Length header to response automatically when possible [#74 state:resolved] [dkubb]
3
+ * Runner now remembers -r, -D and -V parameters so that clustered servers inherit those and
4
+ `restart` keep your parameters.
5
+ * Make Set-Cookie header, in Rails adapter, compatible with current Rack spec [Pedro Belo]
6
+ [#73, state:resolved]
7
+ * Add --no-epoll option to disable epoll usage on Linux [#61 state:resolved]
8
+ * Add --force (-f) option to force stopping of a daemonized server [#72 state:resolved]
9
+ * Update halycon adapter loader [mtodd]
10
+
11
+ == 0.8.2 Double Margarita release
12
+ * Require EventMachine 0.12.0
13
+ * [bug] Fix timeout handling when running command
14
+ * [bug] Fix hanging when restarting and no process is running in single server move, fixes #67
15
+ * Added Mack adapter [markbates]
16
+ * Allow rackup .rb files by getting a conventionally named constant as the app [bmizerany]
17
+
18
+ == 0.8.1 Rebel Porpoise release
19
+ * [bug] Rescue all types of errors when processing request, fixes #62
20
+ * [bug] Use Swiftiply backend when -y option is specified, fixes #63 and #64
21
+ * Allow passing port as a string in Server.new
22
+ * Define deferred?(env) in your Rack application to set if a request is handled in a
23
+ thread (return true) or not (return false).
24
+
25
+ == 0.8.0 Dodgy Dentist release
26
+ * [bug] Fix server crash when header too large.
27
+ * Add --require (-r) option to require a library, before executing your script.
28
+ * Rename --rackup short option to -R, warn and load as rackup when file ends with .ru.
29
+ * List supported adapters in command usage.
30
+ * Add file adapter to built-in adapter, serve static files in current directory.
31
+ * Allow disabling signal handling in Server with :signals => false
32
+ * Make Server.new arguments more flexible, can now specify any of host, port, app or hash options.
33
+ * Add --backend option to specified which backend to use, closes #55
34
+ * [bug] Serve static file only on GET and HEAD requests in Rails adapter, fixes #58
35
+ * Add threaded option to run server in threaded mode, calling the application in a
36
+ thread allowing for concurrency in the Rack adapter, closes #46
37
+ * Guess which adapter to use from directory (chdir option)
38
+ or use specified one in 'adapter' option, re #47.
39
+
40
+ == 0.7.1 Fancy Pants release
41
+ * Clean stale PID files when starting as daemon, fixes #53 [Chu Yeow]
42
+ * Require EventMachine 0.11.0 for UNIX domain sockets. Until it's released, install from:
43
+ gem install eventmachine --source http://code.macournoyer.com
44
+ * Ruby 1.8.5 compatibility, closes #49 [Wincent Colaiuta]
45
+ * Move all EventMachine stuff out of Server, you can now create a Thin Backend that
46
+ does not depend on EventMachine.
47
+ * Rename Connector to Backend. Extend Thin::Backends::Base to implement your own.
48
+ * Fix high memory usage with big POST body, fixes #48
49
+
50
+ == 0.7.0 Spherical Cow release
51
+ * Add --max-persistent-conns option to sets the maximum number of persistent connections.
52
+ Set to 0 to disable Keep-Alive.
53
+ * INT signal now force stop and QUIT signal gracefully stops.
54
+ * Warn when descriptors table size can't be set as high as expected.
55
+ * Eval Rackup config file using top level bindings.
56
+ * Remove daemons gem dependency on Windows plateform, fixes #45.
57
+ * Change default timeout from 60 to 30 seconds.
58
+ * Add --max-conns option to sets the maximum number of file or socket descriptors that
59
+ your process may open, defaults to 1024.
60
+ * Tail logfile when stopping and restarting a demonized server, fixes #26.
61
+ * Wrap application in a Rack::CommonLogger adapter in debug mode.
62
+ * --debug (-D) option no longer set $DEBUG so logging will be less verbose
63
+ and Ruby won't be too strict, fixes #36.
64
+ * Deprecate Server#silent in favour of Logging.silent.
65
+ * Persistent connection (keep-alive) support.
66
+ * Fix -s option not being included in generated config file, fixes #37.
67
+ * Add Swiftiply support. Use w/ the --swiftiply (-y) option in the thin script,
68
+ closes #28 [Alex MacCaw]
69
+
70
+ == 0.6.4 Sexy Lobster release
71
+ * Fix error when stopping server on UNIX domain socket, fixes #42
72
+ * Rescue errors in Connection#get_peername more gracefully, setting REMOTE_ADDR to nil, fixes #43
73
+
74
+ == 0.6.3 Ninja Cookie release
75
+ * Add tasks for Vlad the Deployer in example/vlad.rake [cnantais]
76
+ * Add Ramaze Rackup config file in example dir [tmm1]
77
+ Use like this from you Ramaze app dir:
78
+
79
+ thin start -r /path/to/thin/example/ramaze.ru
80
+
81
+ * Add the --rackup option to load a Rack config file instead of the Rails adapter.
82
+ So you can use any framework with the thin script and start cluster and stuff like that.
83
+ A Rack config file is one that is usable through the rackup command and looks like this:
84
+
85
+ use Rack::CommonLogger
86
+ run MyCrazyRackAdapter.new(:uterly, 'cool')
87
+
88
+ Then use it with thin like this:
89
+
90
+ thin start --rackup config.ru
91
+
92
+ * thin config --chrdir ... -C thin/yml do not change current directory anymore, fixes #33.
93
+ * Add a better sample god config file in example/thin.god that loads all info from config
94
+ files in /etc/thin. Drop-in replacement for the thin runlevel service [Gump].
95
+ * Add support for specifying a custom Connector to the server and add more doc about Server
96
+ configuration.
97
+ * Add a script to run thin as a runlevel service that can start at startup, closes #31 [Gump]
98
+ Setup the service like this:
99
+
100
+ sudo thin install /etc/thin
101
+
102
+ This will install the boot script under /etc/init.d/thin. Then copy your config files to
103
+ /etc/thin. Works only under Linux.
104
+ * Set process name to 'thin server (0.0.0.0:3000)' when running as a daemon, closes #32.
105
+ * Make sure chdir option from config file is used when present.
106
+ * Raise an error when starting a server as a daemon and pid file already exist, fixes #27.
107
+
108
+ == 0.6.2 Rambo release
109
+ * Server now let current connections finish before stopping, fixes #18
110
+ * Fix uploading hanging bug when body is moved to a tempfile,
111
+ also delete the tempfile properly upon completion, fixes #25
112
+ * 'thin restart' now sends HUP signals rather then stopping & starting, closes #17
113
+ * HUP signal now launches a new process with the same options.
114
+ * Add PID and more info from the last request to the Stats adapter
115
+ mostly taken from Rack::ShowException.
116
+ * pid and log files in cluster are no longer required to be relative to the
117
+ app directory (chdir option), fixes #24
118
+ * Revert to using #each when building response headers under Ruby 1.8,
119
+ solves an issue w/ Camping adapter, fixes #22
120
+ * Restructure thin script options in 3 sections: server, daemon and cluster
121
+ * Add --only (-o) option to control only one server of a cluster.
122
+ * Stylize stats page and make the url configurable from the thin script.
123
+ * Raise error if attempting to use unix sockets on windows.
124
+ * Add example config files for http://www.tildeslash.com/monit usage.
125
+ Include the example file using "include /path/to/thin/monit/file" in your monitrc file.
126
+ The group settings let you do this to manage your clusters:
127
+
128
+ sudo monit -g blog restart all
129
+
130
+ There are examples of thin listening on sockets and thin listening on unix sockets.
131
+
132
+ == 0.6.1 Cheesecake release
133
+ * Remove socket file when server stops.
134
+ * Set back cluster to use 'thin' command to launch servers.
135
+
136
+ == 0.6.0 Big Pony release
137
+ * Add support for connection through UNIX domain socket.
138
+ Use the --socket (-S) option w/ the thin script to configure the socket filename.
139
+ Nginx support binding to a UNIX socket like this:
140
+
141
+ upstream backend {
142
+ server unix:/tmp/thin.0.sock;
143
+ server unix:/tmp/thin.1.sock;
144
+ server unix:/tmp/thin.2.sock;
145
+ }
146
+
147
+ Start your servers like this:
148
+
149
+ thin start -s3 -S/tmp/thin.sock
150
+
151
+ * Remove Server#listen! method. Use Server#start instead.
152
+ * Server can now yield a Rack::Builder to allow building an app in one call:
153
+
154
+ Server.start '0.0.0.0', 3000 do
155
+ use Rack::CommonLogger
156
+ use Rack::ShowExceptions
157
+ map "/lobster" do
158
+ use Rack::Lint
159
+ run Rack::Lobster.new
160
+ end
161
+ end
162
+
163
+ * Add a very basic stats page through Stats adapter, load w/ --stats and browse to /stats.
164
+ * Add --trace (-V) option to trace request/response and get backtrace w/out all Ruby debug stuff.
165
+ * Add --config (-C) option to load options from a config file in thin script [Matt Todd].
166
+ * Alter response headers to output directly to a string.
167
+ * Improve specs stability.
168
+ * Move request body to a Tempfile if too big (> 112 MB)
169
+ * Remove useless check for max header size in Request (already done in the parser)
170
+
171
+ == 0.5.4 Flying Mustard release
172
+ * Don't read the full body, use direct streaming when sending response.
173
+ See: Response#each
174
+ As a result, the Content-Length can not be calculated anymore.
175
+ You have to do set this in your adapter. All frameworks do it anyway.
176
+ It improve memory usage and boost speed for low concurrency.
177
+ Thanks to Kent Sibilev and Ezra for their help on that one.
178
+ * Add 'Server' response header
179
+ * Fix --user and --group option not changing daemon process privileges
180
+
181
+ == 0.5.3 Purple Yogurt release
182
+ * win32 pre-compiled gem now available
183
+ * change rake task configuration to allow win32 gem build
184
+ * Add prefix option to thin script to mount app under a given path.
185
+
186
+ == 0.5.2 Cheezburger release
187
+ * Add cluster support through the -s option in the thin script, start 3 thins like this:
188
+ thin start -s3 -p3000
189
+ 3 thin servers will be started on port 3000, 3001, 3002, also the port number will be
190
+ injected in the pid and log filenames.
191
+ * Fix IOError when writing to logger when starting server as a daemon.
192
+ * Really change directory when the -c option is specified.
193
+ * Add restart command to thin script.
194
+ * Fix typos in thin script usage message and expand chdir path.
195
+ * Rename thin script options to be the same as mongrel_rails script [thronedrk]:
196
+ -o --host => -a --address
197
+ --log-file => --log
198
+ --pid-file => --pid
199
+ --env => --environment
200
+
201
+ == 0.5.1 LOLCAT release
202
+ * Add URL rewriting to Rails adapter so that page caching works and / fetches index.html if present.
203
+ * Fix bug in multiline response header parsing.
204
+ * Add specs for the Rails adapter.
205
+ * Fix Set-Cookie headers in Rails adapter to handle multiple values correctly.
206
+ * Fix Ruby 1.9 incompatibility in Response#headers= and Rakefile.
207
+ * Fix parser to be Ruby 1.9 compatible [Aman Gupta]
208
+ * Set gemspec to use EventMachine version 0.8.1 as it's the latest one having precompiled windows binaries.
209
+ [Francis Cianfrocca].
210
+ * Add -D option to thin script to set debugging on.
211
+ * Output incoming data and response when debugging is on.
212
+
213
+ == 0.5.0
214
+ * Full rewrite to use EventMachine, Rack and Mongrel parser
215
+
216
+ == 0.4.1
217
+ * Fix Rails environment option not being used in thin script.
218
+
219
+ == 0.4.0
220
+ * First alphaish release as a gem.
data/COMMITTERS ADDED
@@ -0,0 +1,3 @@
1
+ Marc-Andre Cournoyer <macournoyer@gmail.com>
2
+ Kevin Williams <kevwil@gmail.com>
3
+ James Golick
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2008 Marc-Andre Cournoyer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,77 @@
1
+ == Thin
2
+ Tiny, fast & funny HTTP server
3
+
4
+ Thin is a Ruby web server that glues together 3 of the best Ruby libraries in web history:
5
+ * the Mongrel parser: the root of Mongrel speed and security
6
+ * Event Machine: a network I/O library with extremely high scalability, performance and stability
7
+ * Rack: a minimal interface between webservers and Ruby frameworks
8
+
9
+ Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server
10
+ bundled in an easy to use gem for your own pleasure.
11
+
12
+ Site: http://code.macournoyer.com/thin/
13
+ Group: http://groups.google.com/group/thin-ruby/topics
14
+ Bugs: http://thin.lighthouseapp.com/projects/7212-thin
15
+ Code: http://github.com/macournoyer/thin
16
+ IRC: #thin on freenode
17
+
18
+ === Installation
19
+ For the latest stable version:
20
+
21
+ sudo gem install thin
22
+
23
+ or using my mirror (might be more recent and unstable):
24
+
25
+ sudo gem install thin --source http://code.macournoyer.com
26
+
27
+ Or from source:
28
+
29
+ git clone git://github.com/macournoyer/thin.git
30
+ cd thin
31
+ rake install
32
+
33
+ To use Thin with UNIX domain sockets you need EventMachine 0.11.0 from my gem server:
34
+
35
+ gem install eventmachine --source http://code.macournoyer.com
36
+
37
+ === Usage
38
+ A +thin+ script offers an easy way to start your Rails application:
39
+
40
+ cd to/your/rails/app
41
+ thin start
42
+
43
+ But Thin is also usable with a Rack config file.
44
+ You need to setup a config.ru file and pass it to the thin script:
45
+
46
+ cat config.ru
47
+ app = proc do |env|
48
+ [
49
+ 200,
50
+ {
51
+ 'Content-Type' => 'text/html',
52
+ 'Content-Length' => '2'
53
+ },
54
+ ['hi']
55
+ ]
56
+ end
57
+
58
+ run app
59
+
60
+ thin start -R config.ru
61
+
62
+ See example directory for more samples and run 'thin -h' for usage.
63
+
64
+ === License
65
+ Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
66
+
67
+ === Credits
68
+ The parser was stolen from Mongrel http://mongrel.rubyforge.org by Zed Shaw.
69
+ Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
70
+ <zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
71
+ either the terms of the GPL.
72
+
73
+ Thin is copyright Marc-Andre Cournoyer <macournoyer@gmail.com>
74
+
75
+ Get help at http://groups.google.com/group/thin-ruby/
76
+ Report bugs at http://thin.lighthouseapp.com/projects/7212-thin
77
+ and major security issues directly to a team member (see COMMITTERS)
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
2
+ WIN = (RUBY_PLATFORM =~ /mswin|cygwin/)
3
+ SUDO = (WIN ? "" : "sudo")
4
+
5
+ require 'rake'
6
+ require 'rake/clean'
7
+ require 'lib/thin'
8
+
9
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
10
+
11
+ task :default => :spec
12
+
13
+ ext_task :thin_parser
data/benchmark/abc ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ # Automate benchmarking with ab with various concurrency levels.
3
+ require 'optparse'
4
+
5
+ options = {
6
+ :address => '0.0.0.0',
7
+ :port => 3000,
8
+ :requests => 1000,
9
+ :start => 1,
10
+ :end => 100,
11
+ :step => 10
12
+ }
13
+
14
+ OptionParser.new do |opts|
15
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
16
+
17
+ opts.on("-n", "--requests NUM", "Number of requests") { |num| options[:requests] = num }
18
+ opts.on("-a", "--address HOST", "Address (default: 0.0.0.0)") { |host| options[:address] = host }
19
+ opts.on("-p", "--port PORT", "use PORT (default: 3000)") { |port| options[:port] = port.to_i }
20
+ opts.on("-s", "--start N", "First concurrency level") { |n| options[:start] = n.to_i }
21
+ opts.on("-e", "--end N", "Last concurrency level") { |n| options[:end] = n.to_i }
22
+ opts.on("-S", "--step N", "Concurrency level step") { |n| options[:step] = n.to_i }
23
+ opts.on("-u", "--uri PATH", "Path to send to") { |u| options[:uri] = u }
24
+ opts.on("-k", "--keep-alive", "Use Keep-Alive") { options[:keep_alive] = true }
25
+
26
+ opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
27
+ end.parse!(ARGV)
28
+
29
+ puts 'request concurrency req/s failures'
30
+ puts '=' * 42
31
+
32
+ c = options[:start]
33
+ until c >= options[:end]
34
+ sleep 0.5
35
+ out = `nice -n20 ab #{'-k' if options[:keep_alive]} -c #{c} -n #{options[:requests]} #{options[:address]}:#{options[:port]}/#{options[:uri]} 2> /dev/null`
36
+
37
+ r = if requests = out.match(/^Requests.+?(\d+\.\d+)/)
38
+ requests[1].to_i
39
+ else
40
+ 0
41
+ end
42
+ f = if requests = out.match(/^Failed requests.+?(\d+)/)
43
+ requests[1].to_i
44
+ else
45
+ 0
46
+ end
47
+
48
+ puts "#{options[:requests].to_s.ljust(9)} #{c.to_s.ljust(13)} #{r.to_s.ljust(8)} #{f}"
49
+
50
+ c += options[:step]
51
+ end
@@ -0,0 +1,80 @@
1
+ require 'rack/lobster'
2
+
3
+ class Benchmarker
4
+ PORT = 7000
5
+ ADDRESS = '0.0.0.0'
6
+
7
+ attr_accessor :requests, :concurrencies, :servers, :keep_alive
8
+
9
+ def initialize
10
+ @servers = %w(Mongrel EMongrel Thin)
11
+ @requests = 1000
12
+ @concurrencies = [1, 10, 100]
13
+ end
14
+
15
+ def writer(&block)
16
+ @writer = block
17
+ end
18
+
19
+ def run!
20
+ @concurrencies.each do |concurrency|
21
+ @servers.each do |server|
22
+ req_sec, failed = run_one(server, concurrency)
23
+ @writer.call(server, @requests, concurrency, req_sec, failed)
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+ def start_server(handler_name)
30
+ @server = fork do
31
+ [STDOUT, STDERR].each { |o| o.reopen "/dev/null" }
32
+
33
+ case handler_name
34
+ when 'EMongrel'
35
+ require 'swiftcore/evented_mongrel'
36
+ handler_name = 'Mongrel'
37
+ end
38
+
39
+ app = proc do |env|
40
+ [200, {'Content-Type' => 'text/html', 'Content-Length' => '11'}, ['hello world']]
41
+ end
42
+
43
+ handler = Rack::Handler.const_get(handler_name)
44
+ handler.run app, :Host => ADDRESS, :Port => PORT
45
+ end
46
+
47
+ sleep 2
48
+ end
49
+
50
+ def stop_server
51
+ Process.kill('SIGKILL', @server)
52
+ Process.wait
53
+ end
54
+
55
+ def run_ab(concurrency)
56
+ `nice -n20 ab -c #{concurrency} -n #{@requests} #{@keep_alive ? '-k' : ''} #{ADDRESS}:#{PORT}/ 2> /dev/null`
57
+ end
58
+
59
+ def run_one(handler_name, concurrency)
60
+ start_server(handler_name)
61
+
62
+ out = run_ab(concurrency)
63
+
64
+ stop_server
65
+
66
+ req_sec = if matches = out.match(/^Requests.+?(\d+\.\d+)/)
67
+ matches[1].to_i
68
+ else
69
+ 0
70
+ end
71
+
72
+ failed = if matches = out.match(/^Failed requests.+?(\d+)/)
73
+ matches[1].to_i
74
+ else
75
+ 0
76
+ end
77
+
78
+ [req_sec, failed]
79
+ end
80
+ end