thin 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of thin might be problematic. Click here for more details.

Files changed (91) hide show
  1. data/COPYING +18 -0
  2. data/README +32 -45
  3. data/Rakefile +66 -23
  4. data/bin/thin +76 -45
  5. data/doc/benchmarks.txt +64 -249
  6. data/doc/rdoc/created.rid +1 -1
  7. data/doc/rdoc/files/README.html +37 -100
  8. data/doc/rdoc/rdoc-style.css +5 -0
  9. data/example/config.ru +9 -0
  10. data/ext/thin_parser/common.rl +54 -0
  11. data/ext/thin_parser/ext_help.h +14 -0
  12. data/ext/thin_parser/extconf.rb +6 -0
  13. data/ext/thin_parser/parser.c +1199 -0
  14. data/ext/thin_parser/parser.h +49 -0
  15. data/ext/thin_parser/parser.rl +143 -0
  16. data/ext/thin_parser/thin.c +424 -0
  17. data/lib/rack/adapter/rails.rb +136 -0
  18. data/lib/rack/handler/thin.rb +13 -0
  19. data/lib/thin.rb +28 -12
  20. data/lib/thin/connection.rb +47 -0
  21. data/lib/thin/daemonizing.rb +5 -1
  22. data/lib/thin/headers.rb +3 -2
  23. data/lib/thin/logging.rb +6 -13
  24. data/lib/thin/request.rb +53 -133
  25. data/lib/thin/response.rb +21 -25
  26. data/lib/thin/server.rb +30 -94
  27. data/lib/thin/version.rb +2 -2
  28. data/lib/thin_parser.bundle +0 -0
  29. data/spec/daemonizing_spec.rb +94 -0
  30. data/spec/headers_spec.rb +35 -0
  31. data/spec/request_spec.rb +258 -0
  32. data/spec/response_spec.rb +40 -0
  33. data/spec/server_spec.rb +75 -0
  34. data/spec/spec_helper.rb +126 -0
  35. metadata +79 -99
  36. data/bin/thin_cluster +0 -53
  37. data/doc/rdoc/classes/Kernel.html +0 -182
  38. data/doc/rdoc/classes/Process.html +0 -175
  39. data/doc/rdoc/classes/Thin.html +0 -184
  40. data/doc/rdoc/classes/Thin/CGIWrapper.html +0 -438
  41. data/doc/rdoc/classes/Thin/Cluster.html +0 -392
  42. data/doc/rdoc/classes/Thin/Command.html +0 -221
  43. data/doc/rdoc/classes/Thin/CommandError.html +0 -154
  44. data/doc/rdoc/classes/Thin/Commands.html +0 -145
  45. data/doc/rdoc/classes/Thin/Daemonizable.html +0 -250
  46. data/doc/rdoc/classes/Thin/Daemonizable/ClassMethods.html +0 -203
  47. data/doc/rdoc/classes/Thin/DirHandler.html +0 -250
  48. data/doc/rdoc/classes/Thin/Handler.html +0 -195
  49. data/doc/rdoc/classes/Thin/Headers.html +0 -244
  50. data/doc/rdoc/classes/Thin/InvalidRequest.html +0 -150
  51. data/doc/rdoc/classes/Thin/Logging.html +0 -214
  52. data/doc/rdoc/classes/Thin/RailsHandler.html +0 -234
  53. data/doc/rdoc/classes/Thin/RailsServer.html +0 -175
  54. data/doc/rdoc/classes/Thin/Request.html +0 -379
  55. data/doc/rdoc/classes/Thin/Response.html +0 -311
  56. data/doc/rdoc/classes/Thin/Server.html +0 -381
  57. data/doc/rdoc/files/bin/thin.html +0 -188
  58. data/doc/rdoc/files/bin/thin_cluster.html +0 -175
  59. data/doc/rdoc/files/lib/thin/cgi_rb.html +0 -263
  60. data/doc/rdoc/files/lib/thin/cluster_rb.html +0 -263
  61. data/doc/rdoc/files/lib/thin/command_rb.html +0 -263
  62. data/doc/rdoc/files/lib/thin/consts_rb.html +0 -263
  63. data/doc/rdoc/files/lib/thin/daemonizing_rb.html +0 -263
  64. data/doc/rdoc/files/lib/thin/handler_rb.html +0 -263
  65. data/doc/rdoc/files/lib/thin/headers_rb.html +0 -263
  66. data/doc/rdoc/files/lib/thin/logging_rb.html +0 -263
  67. data/doc/rdoc/files/lib/thin/mime_types_rb.html +0 -263
  68. data/doc/rdoc/files/lib/thin/rails_rb.html +0 -263
  69. data/doc/rdoc/files/lib/thin/recipes_rb.html +0 -171
  70. data/doc/rdoc/files/lib/thin/request_rb.html +0 -171
  71. data/doc/rdoc/files/lib/thin/response_rb.html +0 -171
  72. data/doc/rdoc/files/lib/thin/server_rb.html +0 -171
  73. data/doc/rdoc/files/lib/thin/statuses_rb.html +0 -171
  74. data/doc/rdoc/files/lib/thin/version_rb.html +0 -171
  75. data/lib/thin/cgi.rb +0 -159
  76. data/lib/thin/cluster.rb +0 -147
  77. data/lib/thin/command.rb +0 -49
  78. data/lib/thin/commands/cluster/base.rb +0 -24
  79. data/lib/thin/commands/cluster/config.rb +0 -36
  80. data/lib/thin/commands/cluster/restart.rb +0 -35
  81. data/lib/thin/commands/cluster/start.rb +0 -40
  82. data/lib/thin/commands/cluster/stop.rb +0 -28
  83. data/lib/thin/commands/server/base.rb +0 -7
  84. data/lib/thin/commands/server/start.rb +0 -33
  85. data/lib/thin/commands/server/stop.rb +0 -29
  86. data/lib/thin/consts.rb +0 -37
  87. data/lib/thin/handler.rb +0 -57
  88. data/lib/thin/mime_types.rb +0 -619
  89. data/lib/thin/rails.rb +0 -44
  90. data/lib/thin/recipes.rb +0 -36
  91. data/lib/transat/parser.rb +0 -247
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2007 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 CHANGED
@@ -1,77 +1,64 @@
1
1
  == Thin
2
2
  Tiny, fast & funny HTTP server
3
3
 
4
- Thin is a web server written entirely in Ruby in the simplest way possible.
5
- It does as little as possible to serve your Rails application,
6
- which makes it one of the fastest Rails server out there.
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
+ Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server
9
+ bundled in an easy to use gem for your own pleasure.
7
10
 
8
11
  === Installation
9
12
  For the latest stable version:
10
13
 
11
14
  sudo gem install thin
12
15
 
13
- For the risky but so much cooler alpha version:
16
+ or using my mirror (might be more recent):
14
17
 
15
18
  sudo gem install thin --source http://code.macournoyer.com
16
19
 
17
20
  Or from source:
18
21
 
19
- svn co http://code.macournoyer.com/svn/thin/trunk thin
22
+ git clone http://code.macournoyer.com/git/thin.git
20
23
  cd thin
21
24
  rake install
25
+
26
+ Or from the Subversion mirror (might be out of date):
22
27
 
23
- === Usage
24
- In your Rails app directory:
25
-
26
- thin start
27
-
28
- See http://code.macournoyer.com/thin/doc/files/bin/thin.html
29
-
30
- === Deployment
31
- To deploy your Rails application using a cluster of thin servers. You can start it with:
28
+ svn co http://code.macournoyer.com/svn/thin/trunk thin
32
29
 
33
- thin_cluster start
30
+ === Usage
31
+ A +thin+ script is offered to easily start your Rails application:
34
32
 
35
- To use the Capistrano recipes, add this to your Capfile:
33
+ cd to/your/rails/app
34
+ thin start
36
35
 
36
+ But Thin is also usable through Rack +rackup+ command.
37
+ You need to setup a config.ru file and require thin in it:
38
+
39
+ cat <<EOS
37
40
  require 'thin'
38
- require 'thin/recipes'
39
-
40
- and create a config file using:
41
-
42
- thin_cluster config
43
-
44
- See http://code.macournoyer.com/thin/doc/files/bin/thin_cluster.html
45
-
46
- === Security
47
- Thin should never be used facing the internet directly, it should always be hidden behind a
48
- proxy server!
49
-
50
- Thin is faster because it doesn't do a lot of things that other Ruby web servers do
51
- (use threads, validate the body length, be very strict about the request format, etc.)
52
- but that a good proxy server do very well (and a lot faster then any Ruby code could possibly do).
53
- So it is very important that you setup you proxy server correctly in order to secure Thin
54
- from potential attacks.
55
-
56
- Nginx comes with everything you need and can be used securely out of the box with thin.
57
-
58
- Apache mod_proxy is not secure because it doesn't cache the request before sending it
59
- to the backend, which open your server to easy DoS attacks.
60
- You need to install mod_accel (http://sysoev.ru/en/) to make mod_proxy behave like Nginx
61
- on that side.
41
+
42
+ app = proc do |env|
43
+ [200, {'Content-Type'=>'text/html'}, ['hi']]
44
+ end
45
+
46
+ run app
47
+ EOS
48
+ rackup -s thin
49
+
50
+ See example/config.ru for details and rackup -h
62
51
 
63
52
  === License
64
53
  Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
65
54
 
66
55
  === Credits
67
- Lots of the code was inspired (or stolen entirely) from Mongrel http://mongrel.rubyforge.org by Zed Shaw.
56
+ The parser was stolen from Mongrel http://mongrel.rubyforge.org by Zed Shaw.
68
57
  Mongrel Web Server (Mongrel) is copyrighted free software by Zed A. Shaw
69
58
  <zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
70
59
  either the terms of the GPL.
71
60
 
72
- transat/parser.rb was taken from Piston source code.
73
- Copyright (c) 2006 Francois Beausoleil <francois@teksol.info>
74
-
75
61
  Thin is copyright Marc-Andre Cournoyer <macournoyer@gmail.com>
76
62
 
77
- Please report any bug at http://code.macournoyer.com/thin/trac.fcgi/newticket
63
+ Please report any bug at http://code.macournoyer.com/thin/trac.fcgi/newticket
64
+ and security issues directly to me at macournoyer@gmail.com.
data/Rakefile CHANGED
@@ -1,18 +1,28 @@
1
1
  require 'rake'
2
2
  require 'rake/clean'
3
- require 'rake/testtask'
4
3
  require 'rake/rdoctask'
5
4
  require 'rake/gempackagetask'
5
+ require 'spec/rake/spectask'
6
6
 
7
7
  require File.dirname(__FILE__) + '/lib/thin'
8
8
 
9
- REVISION = `svn info`.match('Revision: (\d+)')[1]
10
- CLEAN.include %w(doc/rdoc pkg tmp log)
11
-
12
- Rake::TestTask.new do |t|
13
- t.pattern = 'test/*_test.rb'
9
+ EXT_DIR = 'ext/thin_parser'
10
+ EXT_BUNDLE = "#{EXT_DIR}/thin_parser.#{Config::CONFIG['DLEXT']}"
11
+ EXT_FILES = FileList[
12
+ "#{EXT_DIR}/*.c",
13
+ "#{EXT_DIR}/*.h",
14
+ "#{EXT_DIR}/*.rl",
15
+ "#{EXT_DIR}/extconf.rb",
16
+ "#{EXT_DIR}/Makefile",
17
+ "lib"
18
+ ]
19
+ CLEAN.include %w(doc/rdoc pkg coverage tmp log *.gem **/*.{o,bundle,jar,so,obj,pdb,lib,def,exp,log} ext/*/Makefile ext/*/conftest.dSYM)
20
+
21
+ desc "Run all examples"
22
+ Spec::Rake::SpecTask.new('spec') do |t|
23
+ t.spec_files = FileList['spec/**/*.rb']
14
24
  end
15
- task :default => :test
25
+ task :default => [:compile, :spec]
16
26
 
17
27
  Rake::RDocTask.new do |rdoc|
18
28
  rdoc.rdoc_dir = 'doc/rdoc'
@@ -24,7 +34,7 @@ Rake::RDocTask.new do |rdoc|
24
34
  rdoc.template = "site/rdoc.rb"
25
35
  rdoc.main = "README"
26
36
  rdoc.title = Thin::NAME
27
- rdoc.rdoc_files.add ['README', 'lib/thin/*.rb', 'bin/*']
37
+ rdoc.rdoc_files.add %w(README lib/thin/*.rb')
28
38
  end
29
39
 
30
40
  namespace :rdoc do
@@ -38,16 +48,22 @@ spec = Gem::Specification.new do |s|
38
48
  s.name = Thin::NAME
39
49
  s.version = Thin::VERSION::STRING
40
50
  s.platform = Gem::Platform::RUBY
41
- s.summary = "Thin and fast web server"
42
- s.description = s.summary
51
+ s.summary =
52
+ s.description = "A thin and fast web server"
43
53
  s.author = "Marc-Andre Cournoyer"
44
54
  s.email = 'macournoyer@gmail.com'
45
55
  s.homepage = 'http://code.macournoyer.com/thin/'
46
- s.executables = %w(thin thin_cluster)
56
+ s.executables = %w(thin)
47
57
 
48
- s.required_ruby_version = '>= 1.8.6' # To be sure the multipart eof fix is in there
58
+ s.required_ruby_version = '>= 1.8.6'
59
+
60
+ s.add_dependency 'eventmachine', '>= 0.9.0'
61
+ s.add_dependency 'rack', '>= 0.2.0'
49
62
 
50
- s.files = %w(README Rakefile) + Dir.glob("{bin,doc,lib}/**/*")
63
+ s.files = %w(COPYING README Rakefile) +
64
+ Dir.glob("{bin,doc,spec,lib,example}/**/*") +
65
+ Dir.glob("ext/**/*.{h,c,rb,rl}") +
66
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
51
67
 
52
68
  s.require_path = "lib"
53
69
  s.bindir = "bin"
@@ -72,14 +88,45 @@ namespace :gem do
72
88
  end
73
89
  end
74
90
 
91
+ task :ragel do
92
+ Dir.chdir EXT_DIR do
93
+ target = "parser.c"
94
+ File.unlink target if File.exist? target
95
+ sh "ragel parser.rl | rlgen-cd -G2 -o #{target}"
96
+ raise "Failed to compile Ragel state machine" unless File.exist? target
97
+ end
98
+ end
99
+
100
+ desc "Compile the extensions"
101
+ task :compile => ["#{EXT_DIR}/Makefile", EXT_BUNDLE]
102
+
103
+ task :package => :compile
104
+
105
+ file "#{EXT_DIR}/Makefile" => ["#{EXT_DIR}/extconf.rb"] do
106
+ cd(EXT_DIR) { ruby "extconf.rb" }
107
+ end
108
+
109
+ file EXT_BUNDLE => EXT_FILES do
110
+ cd EXT_DIR do
111
+ sh(PLATFORM =~ /win32/ ? 'nmake' : 'make')
112
+ end
113
+ cp EXT_BUNDLE, 'lib/'
114
+ end
115
+
75
116
  desc 'Show some stats about the code'
76
117
  task :stats do
77
118
  line_count = proc do |path|
78
- Dir[path].collect { |f| File.open(f).readlines.reject { |l| l =~ /^\s*\#/ }.size }.inject(0){ |sum,n| sum += n }
119
+ Dir[path].collect { |f| File.open(f).readlines.reject { |l| l =~ /(^\s*(\#|\/\*))|^\s*$/ }.size }.inject(0){ |sum,n| sum += n }
79
120
  end
80
- puts "#{line_count['lib/**/*.rb'].to_s.rjust(6)} LOC of lib"
81
- puts "#{line_count['lib/thin/{server,request,response,cgi,rails,handler,headers}.rb'].to_s.rjust(6)} LOC of web serving stuff"
82
- puts "#{line_count['test/**/*.rb'].to_s.rjust(6)} LOC of test"
121
+ lib = line_count['lib/**/*.rb']
122
+ ext = line_count['ext/**/*.{c,h}']
123
+ test = line_count['test/**/*.rb']
124
+ ratio = '%1.2f' % (test.to_f / lib.to_f)
125
+
126
+ puts "#{lib.to_s.rjust(6)} LOC of lib"
127
+ puts "#{ext.to_s.rjust(6)} LOC of ext"
128
+ puts "#{test.to_s.rjust(6)} LOC of test"
129
+ puts "#{ratio.to_s.rjust(6)} ratio lib/test"
83
130
  end
84
131
 
85
132
  namespace :site do
@@ -110,19 +157,15 @@ end
110
157
  desc 'Deploy on all servers'
111
158
  task :deploy => %w(deploy:alpha deploy:public)
112
159
 
113
- task :install do
160
+ task :install => :compile do
114
161
  sh %{rake package}
115
162
  sh %{sudo gem install pkg/#{Thin::NAME}-#{Thin::VERSION::STRING}}
116
163
  end
117
164
 
118
- task :uninstall => [:clean] do
165
+ task :uninstall => :clean do
119
166
  sh %{sudo gem uninstall #{Thin::NAME}}
120
167
  end
121
168
 
122
- task :tag do
123
- sh %Q{svn cp . http://code.macournoyer.com/svn/thin/tags/#{Thin::VERSION::STRING} -m "Tagging version #{Thin::VERSION::STRING}"}
124
- end
125
-
126
169
  # == Utilities
127
170
 
128
171
  def upload(file, to, options={})
data/bin/thin CHANGED
@@ -1,48 +1,79 @@
1
1
  #!/usr/bin/env ruby
2
- # == thin
3
- # Script to launch a Thin server for a Rails application.
4
- #
5
- # To start a server for your current Rails app:
6
- # thin start
7
- # You can specify the port using the -p option:
8
- # thin start -p3001
9
- # By default the server will bind to 0.0.0.0:3000
10
- #
11
- # You can specify which Rails environment should be loaded with the -e option:
12
- # thin start -e production
13
- #
14
- # You can also start the server in daemon mode:
15
- # thin start -d
16
- # And later stop it
17
- # thin stop
18
- #
19
- # Run <tt>thin help</tt> to get help.
20
-
21
2
  require File.dirname(__FILE__) + '/../lib/thin'
22
- require 'thin/command'
23
-
24
- Thin.define_commands do
25
- program_name 'thin'
26
- version Thin::VERSION::STRING
27
- help 'Thin is a web server that can run your Rails app in no time'
28
-
29
- option :address, :short => :a, :default => '0.0.0.0', :message => 'Address to bind to',
30
- :param_name => 'ADDRESS'
31
- option :port, :short => :p, :default => 3000, :message => 'Port number to bind to',
32
- :param_name => 'PORT', :type => :int
33
- option :environment, :short => :e, :default => 'development', :message => 'Rails environment',
34
- :param_name => 'ENVIRONMENT'
35
- option :log_file, :short => :l, :default => 'log/thin.log', :message => 'File to write log output to (use with -d)',
36
- :param_name => 'PATH'
37
- option :pid_file, :short => :P, :default => 'tmp/pids/thin.pid', :message => 'File to write the PID (use with -d)',
38
- :param_name => 'PATH'
39
- option :daemonize, :short => :d, :message => 'Run in the background'
40
- option :user, :short => :u, :param_name => 'USER', :message => 'User to run the process as'
41
- option :group, :short => :g, :param_name => 'GROUP', :message => 'Group to run the process as'
42
- option :timeout, :short => :T, :param_name => 'SEC', :message => 'Server timeout before giving up',
43
- :default => 60
44
- option :trace, :short => :t, :message => 'Turn trace on'
45
-
46
- command :start, Thin::Commands::Server::Start, :valid_options => [:address, :port, :environment, :log_file, :daemonize, :pid_file, :user, :group, :trace, :timeout]
47
- command :stop, Thin::Commands::Server::Stop, :valid_options => [:pid_file, :timeout]
3
+ require 'optparse'
4
+
5
+ options = {
6
+ :root => Dir.pwd,
7
+ :env => 'development',
8
+ :host => '0.0.0.0',
9
+ :port => 3000,
10
+ :timeout => 60,
11
+ :log_file => 'log/thin.log',
12
+ :pid_file => 'tmp/pids/thin.pid'
13
+ }
14
+
15
+ opts = OptionParser.new do |opts|
16
+ opts.banner = "Usage: thin [options] start|stop"
17
+
18
+ opts.separator ""
19
+ opts.separator "Server options:"
20
+
21
+ opts.on("-o", "--host HOST", "listen on HOST (default: 0.0.0.0)") { |host| options[:host] = host }
22
+ opts.on("-p", "--port PORT", "use PORT (default: 3000)") { |port| options[:port] = port }
23
+ opts.on("-e", "--env ENV", "Rails environment (default: development)") { |env| options[:env] = env }
24
+ opts.on("-c", "--chdir PATH", "listen on HOST (default: current dir)") { |dir| options[:root] = dir }
25
+ opts.on("-d", "--daemonize", "Daemonize") { options[:daemonize] = true }
26
+ opts.on("-l", "--log-file FILE", "File to redirect output",
27
+ "(default: #{options[:log_file]})") { |file| options[:log_file] = file }
28
+ opts.on("-P", "--pid-file FILE", "File to store PID",
29
+ "(default: #{options[:pid_file]})") { |file| options[:pid_file] = file }
30
+ opts.on("-t", "--timeout SEC", "Request or command timeout in sec",
31
+ "(default: #{options[:timeout]})") { |sec| options[:timeout] = sec }
32
+ opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| options[:user] = user }
33
+ opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| options[:group] = group }
34
+
35
+ opts.separator ""
36
+ opts.separator "Common options:"
37
+
38
+ opts.on_tail("-h", "--help", "Show this message") do
39
+ puts opts
40
+ exit
41
+ end
42
+
43
+ opts.on_tail('-v', '--version', "Show version") do
44
+ puts Thin::NAME
45
+ exit
46
+ end
47
+
48
+ opts.parse! ARGV
49
+ end
50
+
51
+ case ARGV[0]
52
+
53
+ when 'start'
54
+ app = Rack::Adapter::Rails.new(options)
55
+ server = Thin::Server.new(options[:host], options[:port], app)
56
+
57
+ server.pid_file = options[:pid_file]
58
+ server.log_file = options[:log_file]
59
+ server.timeout = options[:timeout]
60
+
61
+ if options[:daemonize]
62
+ server.change_privilege options[:user], options[:group] if options[:user] && options[:group]
63
+ server.daemonize
64
+ end
65
+
66
+ server.start!
67
+
68
+ when 'stop'
69
+ Thin::Server.kill options[:pid_file], options[:timeout]
70
+
71
+ when nil
72
+ puts "Command required"
73
+ puts opts
74
+ exit 1
75
+
76
+ else
77
+ abort "Invalid command : #{ARGV[0]}"
78
+
48
79
  end
@@ -1,271 +1,86 @@
1
- = Benchmark Thin vs Mongrel
1
+ == Process
2
+ * rackup ...
3
+ * nice -n20 httperf --port 9292 --num-conns 9000
4
+ * nice -n20 ab -n5000 localhost:9292/
5
+ * nice -n20 ab -n5000 -c10 localhost:9292/
6
+ * nice -n20 ab -n5000 -c100 localhost:9292/
2
7
 
3
- == Single instance
4
- On server instance. Running Rails in development environment.
5
- App is http://refactormycode.com with no caching.
8
+ == More Benchmarks
9
+ http://www.webficient.com/2007/08/testing-various-configurations-of-rails.html
6
10
 
7
- === Thin
8
- marc:~ marc$ ab -n10 -c3 localhost:3000/
9
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
10
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
11
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
12
-
13
- Benchmarking localhost (be patient).....done
14
- Server Software: thin
15
- Server Hostname: localhost
16
- Server Port: 3000
17
-
18
- Document Path: /
19
- Document Length: 11195 bytes
11
+ === WEBrick
12
+ rackup -s webrick
20
13
 
21
- Concurrency Level: 3
22
- Time taken for tests: 15.429 seconds
23
- Complete requests: 10
24
- Failed requests: 0
25
- Broken pipe errors: 0
26
- Total transferred: 114510 bytes
27
- HTML transferred: 111950 bytes
28
- Requests per second: 0.65 [#/sec] (mean)
29
- Time per request: 4628.70 [ms] (mean)
30
- Time per request: 1542.90 [ms] (mean, across all concurrent requests)
31
- Transfer rate: 7.42 [Kbytes/sec] received
32
-
33
- Connnection Times (ms)
34
- min mean[+/-sd] median max
35
- Connect: 0 0 0.0 0 0
36
- Processing: 1935 4175 874.1 4458 4903
37
- Waiting: 1935 4175 874.1 4458 4903
38
- Total: 1935 4175 874.1 4458 4903
39
-
40
- Percentage of the requests served within a certain time (ms)
41
- 50% 4458
42
- 66% 4525
43
- 75% 4562
44
- 80% 4597
45
- 90% 4903
46
- 95% 4903
47
- 98% 4903
48
- 99% 4903
49
- 100% 4903 (last request)
50
-
51
- === Mongrel
52
- marc:~ marc$ ab -n10 -c3 localhost:3001/
53
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
54
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
55
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
14
+ ==== httperf
15
+ Reply rate [replies/s]: min 303.8 avg 306.8 max 310.4 stddev 2.8 (5 samples)
16
+ Reply rate [replies/s]: min 235.8 avg 292.2 max 306.4 stddev 27.7 (6 samples)
17
+ Reply rate [replies/s]: min 304.8 avg 306.9 max 308.8 stddev 1.5 (5 samples)
18
+ avg: 302.0 10.7
56
19
 
57
- Benchmarking localhost (be patient).....done
58
- Server Software: Mongrel
59
- Server Hostname: localhost
60
- Server Port: 3001
20
+ ==== Concurrency Level 1
21
+ 297.37 [#/sec] (mean)
61
22
 
62
- Document Path: /
63
- Document Length: 11195 bytes
23
+ ==== Concurrency Level 10
24
+ 296.65 [#/sec] (mean) Failed requests: 4 (Connect: 2, Length: 2, Exceptions: 0)
25
+ 298.22 [#/sec] (mean) Failed requests: 4 (Connect: 2, Length: 2, Exceptions: 0)
64
26
 
65
- Concurrency Level: 3
66
- Time taken for tests: 16.522 seconds
67
- Complete requests: 10
68
- Failed requests: 0
69
- Broken pipe errors: 0
70
- Total transferred: 114930 bytes
71
- HTML transferred: 111950 bytes
72
- Requests per second: 0.61 [#/sec] (mean)
73
- Time per request: 4956.60 [ms] (mean)
74
- Time per request: 1652.20 [ms] (mean, across all concurrent requests)
75
- Transfer rate: 6.96 [Kbytes/sec] received
76
-
77
- Connnection Times (ms)
78
- min mean[+/-sd] median max
79
- Connect: 0 0 0.0 0 0
80
- Processing: 2629 4496 746.2 4662 5602
81
- Waiting: 2629 4496 746.2 4662 5602
82
- Total: 2629 4496 746.2 4662 5602
83
-
84
- Percentage of the requests served within a certain time (ms)
85
- 50% 4662
86
- 66% 4681
87
- 75% 4691
88
- 80% 4715
89
- 90% 5602
90
- 95% 5602
91
- 98% 5602
92
- 99% 5602
93
- 100% 5602 (last request)
94
-
95
- == Cluster
96
- Using Nginx as the load balancer with 3 app instance.
97
- App is http://refactormycode.com with no caching.
98
-
99
- === Thin
100
- marc:~ marc$ ab -n10 -c5 localhost/
101
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
102
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
103
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
27
+ ==== Concurrency Level 100
28
+ 297.16 [#/sec] (mean) Failed requests: 489 (Connect: 245, Length: 244, Exceptions: 0)
104
29
 
105
- Benchmarking localhost (be patient).....done
106
- Server Software: nginx/0.5.33
107
- Server Hostname: localhost
108
- Server Port: 80
109
30
 
110
- Document Path: /
111
- Document Length: 45456 bytes
112
-
113
- Concurrency Level: 5
114
- Time taken for tests: 4.444 seconds
115
- Complete requests: 10
116
- Failed requests: 0
117
- Broken pipe errors: 0
118
- Total transferred: 458270 bytes
119
- HTML transferred: 454560 bytes
120
- Requests per second: 2.25 [#/sec] (mean)
121
- Time per request: 2222.00 [ms] (mean)
122
- Time per request: 444.40 [ms] (mean, across all concurrent requests)
123
- Transfer rate: 103.12 [Kbytes/sec] received
124
-
125
- Connnection Times (ms)
126
- min mean[+/-sd] median max
127
- Connect: 0 0 0.0 0 0
128
- Processing: 1031 1703 1064.3 1185 4119
129
- Waiting: 1031 1703 1064.3 1185 4119
130
- Total: 1031 1703 1064.3 1185 4119
131
-
132
- Percentage of the requests served within a certain time (ms)
133
- 50% 1185
134
- 66% 1207
135
- 75% 2178
136
- 80% 2978
137
- 90% 4119
138
- 95% 4119
139
- 98% 4119
140
- 99% 4119
141
- 100% 4119 (last request)
142
- marc:~ marc$ ab -n100 -c10 localhost/
143
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
144
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
145
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
146
-
147
- Benchmarking localhost (be patient).....done
148
- Server Software: nginx/0.5.33
149
- Server Hostname: localhost
150
- Server Port: 80
151
-
152
- Document Path: /
153
- Document Length: 45456 bytes
154
-
155
- Concurrency Level: 10
156
- Time taken for tests: 36.949 seconds
157
- Complete requests: 100
158
- Failed requests: 0
159
- Broken pipe errors: 0
160
- Total transferred: 4582700 bytes
161
- HTML transferred: 4545600 bytes
162
- Requests per second: 2.71 [#/sec] (mean)
163
- Time per request: 3694.90 [ms] (mean)
164
- Time per request: 369.49 [ms] (mean, across all concurrent requests)
165
- Transfer rate: 124.03 [Kbytes/sec] received
31
+ === Mongrel
32
+ rackup -s mongrel
166
33
 
167
- Connnection Times (ms)
168
- min mean[+/-sd] median max
169
- Connect: 0 0 0.0 0 0
170
- Processing: 996 3502 762.1 3539 4841
171
- Waiting: 996 3502 762.3 3539 4841
172
- Total: 996 3502 762.1 3539 4841
34
+ ==== httperf
35
+ Reply rate [replies/s]: min 556.4 avg 580.1 max 613.6 stddev 29.9 (3 samples)
36
+ Reply rate [replies/s]: min 299.0 avg 502.6 max 613.4 stddev 176.5 (3 samples)
37
+ Reply rate [replies/s]: min 601.0 avg 608.5 max 616.0 stddev 10.7 (2 samples)
38
+ Reply rate [replies/s]: min 605.2 avg 608.4 max 611.6 stddev 4.5 (2 samples)
39
+ avg: 574.9 55.4
173
40
 
174
- Percentage of the requests served within a certain time (ms)
175
- 50% 3539
176
- 66% 3947
177
- 75% 4167
178
- 80% 4229
179
- 90% 4417
180
- 95% 4563
181
- 98% 4742
182
- 99% 4841
183
- 100% 4841 (last request)
41
+ ==== Concurrency Level 1
42
+ 556.67 [#/sec] (mean)
184
43
 
44
+ ==== Concurrency Level 10
45
+ 622.90 [#/sec] (mean)
185
46
 
186
- === Mongrel
47
+ ==== Concurrency Level 100
48
+ 428.23 [#/sec] (mean)
187
49
 
188
- marc:~ marc$ ab -n10 -c5 localhost/
189
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
190
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
191
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
50
+ === Evented Mongrel
51
+ rackup -r "swiftcore/evented_mongrel" -s mongrel
192
52
 
193
- Benchmarking localhost (be patient).....done
194
- Server Software: nginx/0.5.33
195
- Server Hostname: localhost
196
- Server Port: 80
53
+ ==== httperf
54
+ Reply rate [replies/s]: min 452.4 avg 541.0 max 590.0 stddev 76.9 (3 samples)
55
+ Reply rate [replies/s]: min 573.2 avg 586.0 max 593.0 stddev 11.1 (3 samples)
56
+ Reply rate [replies/s]: min 546.6 avg 574.8 max 594.6 stddev 25.0 (3 samples)
57
+ Reply rate [replies/s]: min 593.6 avg 595.2 max 596.4 stddev 1.5 (3 samples)
58
+ avg: 574.25 28.625
197
59
 
198
- Document Path: /
199
- Document Length: 45455 bytes
60
+ ==== Concurrency Level 1
61
+ 517.97 [#/sec] (mean)
200
62
 
201
- Concurrency Level: 5
202
- Time taken for tests: 5.995 seconds
203
- Complete requests: 10
204
- Failed requests: 0
205
- Broken pipe errors: 0
206
- Total transferred: 458600 bytes
207
- HTML transferred: 454550 bytes
208
- Requests per second: 1.67 [#/sec] (mean)
209
- Time per request: 2997.50 [ms] (mean)
210
- Time per request: 599.50 [ms] (mean, across all concurrent requests)
211
- Transfer rate: 76.50 [Kbytes/sec] received
63
+ ==== Concurrency Level 10
64
+ 657.89 [#/sec] (mean)
212
65
 
213
- Connnection Times (ms)
214
- min mean[+/-sd] median max
215
- Connect: 0 0 0.0 0 0
216
- Processing: 1248 2500 1138.1 2743 4245
217
- Waiting: 1248 2500 1138.0 2743 4245
218
- Total: 1248 2500 1138.1 2743 4245
66
+ ==== Concurrency Level 100
67
+ 656.17 [#/sec] (mean)
219
68
 
220
- Percentage of the requests served within a certain time (ms)
221
- 50% 2743
222
- 66% 3040
223
- 75% 3148
224
- 80% 4131
225
- 90% 4245
226
- 95% 4245
227
- 98% 4245
228
- 99% 4245
229
- 100% 4245 (last request)
230
- marc:~ marc$ ab -n100 -c10 localhost/
231
- This is ApacheBench, Version 1.3d <$Revision: 1.73 $> apache-1.3
232
- Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
233
- Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
234
-
235
- Benchmarking localhost (be patient).....done
236
- Server Software: nginx/0.5.33
237
- Server Hostname: localhost
238
- Server Port: 80
69
+ === Thin
70
+ rackup -s thin
239
71
 
240
- Document Path: /
241
- Document Length: 45455 bytes
72
+ ==== httperf
73
+ Reply rate [replies/s]: min 671.4 avg 681.0 max 690.7 stddev 13.6 (2 samples)
74
+ Reply rate [replies/s]: min 690.0 avg 695.8 max 701.7 stddev 8.3 (2 samples)
75
+ Reply rate [replies/s]: min 643.4 avg 669.4 max 695.4 stddev 36.7 (2 samples)
76
+ Reply rate [replies/s]: min 694.1 avg 695.8 max 697.6 stddev 2.5 (2 samples)
77
+ avg: 685.5 15.275
242
78
 
243
- Concurrency Level: 10
244
- Time taken for tests: 41.135 seconds
245
- Complete requests: 100
246
- Failed requests: 0
247
- Broken pipe errors: 0
248
- Total transferred: 4586000 bytes
249
- HTML transferred: 4545500 bytes
250
- Requests per second: 2.43 [#/sec] (mean)
251
- Time per request: 4113.50 [ms] (mean)
252
- Time per request: 411.35 [ms] (mean, across all concurrent requests)
253
- Transfer rate: 111.49 [Kbytes/sec] received
79
+ ==== Concurrency Level 1
80
+ 719.53 [#/sec] (mean)
254
81
 
255
- Connnection Times (ms)
256
- min mean[+/-sd] median max
257
- Connect: 0 0 0.0 0 0
258
- Processing: 1600 3921 640.4 3877 5694
259
- Waiting: 1600 3921 640.4 3877 5694
260
- Total: 1600 3921 640.4 3877 5694
82
+ ==== Concurrency Level 10
83
+ 782.11 [#/sec] (mean)
261
84
 
262
- Percentage of the requests served within a certain time (ms)
263
- 50% 3877
264
- 66% 4187
265
- 75% 4353
266
- 80% 4402
267
- 90% 4585
268
- 95% 4919
269
- 98% 5351
270
- 99% 5694
271
- 100% 5694 (last request)
85
+ ==== Concurrency Level 100
86
+ 776.40 [#/sec] (mean)