webrick-high-performance 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/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright 2005 Eric Hodel, The Robot Co-op. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ 3. Neither the names of the authors nor the names of their contributors
13
+ may be used to endorse or promote products derived from this software
14
+ without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
17
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
20
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
@@ -0,0 +1,5 @@
1
+ LICENSE
2
+ Manifest.txt
3
+ README
4
+ Rakefile
5
+ lib/webrick/highperformanceserver.rb
data/README ADDED
@@ -0,0 +1,54 @@
1
+ = WEBrick High Performance
2
+
3
+ Rubyforge Project:
4
+
5
+ http://rubyforge.org/projects/rctools/
6
+
7
+ Documentation:
8
+
9
+ http://dev.robotcoop.com/Libraries/webrick-high-performance/
10
+
11
+ == About
12
+
13
+ WEBrick High Performance adds a new HTTP server class that takes advantage of
14
+ sendfile(2) and fork(2) to drastically improve static file server performance.
15
+
16
+ Since HighPerformanceServer is a forking webserver it may also speed up regular
17
+ WEBrick servlets by spreading load across multiple CPUs.
18
+
19
+ The sendfile(2) system call allows web server writers to offload the job of
20
+ transfering files from the disk to the socket onto the kernel. The work of
21
+ parsing HTTP headers is very easy and very fast and WEBrick is nearly fast
22
+ enough to match Apache.
23
+
24
+ When additional work is needed to look up or validate file access (for example,
25
+ the file is stored in MogileFS) it is more performant to write the code in Ruby
26
+ and use HighPerformanceServer than to write a FastCGI handler and easier than writing an Apache module.
27
+
28
+ == Installing webrick-high-performance
29
+
30
+ webrick-high-performance depends upon socket_sendfile, and as of 1.0.0
31
+ socket_sendfile is only known to work on FreeBSD.
32
+
33
+ So if you've got FreeBSD you only need to install the gem:
34
+
35
+ $ sudo gem install webrick-high-performance
36
+
37
+ == Using webrick-high-performance
38
+
39
+ #!/usr/local/bin/ruby -w
40
+
41
+ require 'rubygems'
42
+ require 'webrick'
43
+ require 'webrick/highperformanceserver'
44
+
45
+ config = {}
46
+ config[:Port] = 8000
47
+ config[:Root] = File.expand_path '~/public_html'
48
+
49
+ WEBrick::HighPerformanceServer.create config do |server|
50
+ trap 'INT' do server.shutdown end
51
+ trap 'TERM' do server.shutdown end
52
+ server.start
53
+ end
54
+
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+
7
+ $VERBOSE = nil
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'webrick-high-performance'
11
+ s.version = '1.0.0'
12
+ s.summary = 'A high-performance WEBrick server'
13
+ s.description = 'A high-performance WEBrick server that takes advantage of sendfile(2) and fork(2) to serve static files really fast.'
14
+ s.author = 'Eric Hodel'
15
+ s.email = 'eric@robotcoop.com'
16
+
17
+ s.has_rdoc = true
18
+ s.files = File.read('Manifest.txt').split($/)
19
+ s.require_path = 'lib'
20
+
21
+ s.test_files = Dir.glob('test/test_*.rb')
22
+
23
+ s.add_dependency 'socket_sendfile', '>= 1.1.0'
24
+ s.add_dependency 'socket_accept_filter', '>= 1.0.0'
25
+ end
26
+
27
+ desc 'Run tests'
28
+ task :default => [ :test ]
29
+
30
+ Rake::TestTask.new('test') do |t|
31
+ t.libs << 'test'
32
+ t.pattern = 'test/test_*.rb'
33
+ t.verbose = true
34
+ end
35
+
36
+ desc 'Update Manifest.txt'
37
+ task :update_manifest do
38
+ sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
39
+ end
40
+
41
+ desc 'Generate RDoc'
42
+ Rake::RDocTask.new :rdoc do |rd|
43
+ rd.rdoc_dir = 'doc'
44
+ rd.rdoc_files.add 'lib', 'README', 'LICENSE'
45
+ rd.main = 'README'
46
+ rd.options << '-d' if `which dot` =~ /\/dot/
47
+ end
48
+
49
+ desc 'Generate RDoc for dev.robotcoop.com'
50
+ Rake::RDocTask.new :dev_rdoc do |rd|
51
+ rd.rdoc_dir = '../../../www/trunk/dev/html/Libraries/webrick-high-performance'
52
+ rd.rdoc_files.add 'lib', 'README', 'LICENSE'
53
+ rd.main = 'README'
54
+ rd.options << '-d' if `which dot` =~ /\/dot/
55
+ end
56
+
57
+ desc 'Build Gem'
58
+ Rake::GemPackageTask.new spec do |pkg|
59
+ pkg.need_tar = true
60
+ end
61
+
62
+ desc 'Clean up'
63
+ task :clean => [ :clobber_rdoc, :clobber_package ]
64
+
65
+ desc 'Clean up'
66
+ task :clobber => [ :clean ]
67
+
68
+ # vim: syntax=Ruby
69
+
@@ -0,0 +1,156 @@
1
+ require 'webrick'
2
+ require 'socket_accept_filter' rescue LoadError
3
+ require 'socket_sendfile'
4
+
5
+ class WEBrick::HTTPResponse # :nodoc:
6
+
7
+ alias old_send_body_io send_body_io
8
+ alias old_chunked? chunked?
9
+
10
+ def chunked?
11
+ return @body.is_a?(File) ? false : @chunked
12
+ end
13
+
14
+ ##
15
+ # Copied from WEBrick::HTTPResponse to add sendfile support.
16
+
17
+ def send_body_io(socket)
18
+ socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 # HACK yuck
19
+
20
+ if @request_method == "HEAD"
21
+ # do nothing
22
+ elsif @body.kind_of? File
23
+ socket.sendfile @body
24
+ elsif chunked?
25
+ while buf = @body.read(BUFSIZE)
26
+ next if buf.empty?
27
+ data = ""
28
+ data << format("%x", buf.size) << CRLF
29
+ data << buf << CRLF
30
+ _write_data(socket, data)
31
+ @sent_size += buf.size
32
+ end
33
+ _write_data(socket, "0#{CRLF}#{CRLF}")
34
+ else
35
+ size = @header['content-length'].to_i
36
+ _send_file(socket, @body, 0, size)
37
+ @sent_size = size
38
+ end
39
+ ensure
40
+ @body.close
41
+ end
42
+
43
+ end
44
+
45
+ module WEBrick::Config
46
+
47
+ ##
48
+ # HighPerformanceServer default configuration.
49
+
50
+ HighPerformance = HTTP.dup.update(
51
+ :RequestTimeout => 2,
52
+ :Processes => 8
53
+ )
54
+
55
+ end
56
+
57
+ ##
58
+ # A high performance WEBrick server that takes advantage of sendfile(2) and
59
+ # fork(2) to drastically increase the performance of serving static files.
60
+ #
61
+ # Instead of starting a HighPerformanceServer like a regular HTTPServer, use
62
+ # HighPerformanceServer::create.
63
+
64
+ class WEBrick::HighPerformanceServer < WEBrick::HTTPServer
65
+
66
+ ##
67
+ # This process starts up a bunch of listeners than forks children to do the
68
+ # actual work.
69
+
70
+ @listeners = []
71
+
72
+ class << self
73
+
74
+ ##
75
+ # Server sockets for my children.
76
+
77
+ attr_accessor :listeners
78
+
79
+ ##
80
+ # Creates :Processes new HighPerformanceServers all listening on the same
81
+ # server sockets.
82
+ #
83
+ # +config+ and +default+ work the same as they do for HTTPServer.
84
+ #
85
+ # yields each forked child's server object. The server will not be
86
+ # started nor will signals be caught.
87
+ #
88
+ # Returns the pids of the created HighPerformanceServer children.
89
+ #
90
+ # Typical usage:
91
+ #
92
+ # WEBrick::HighPerformanceServer.create do |server|
93
+ # server.mount '/', WEBrick::HTTPServlet::FileHandler,
94
+ # '/usr/local/www/data'
95
+ # trap 'INT' do server.shutdown end
96
+ # trap 'TERM' do server.shutdown end
97
+ # server.start
98
+ # end
99
+
100
+ def create(config = {}, default = WEBrick::Config::HighPerformance)
101
+ config = default.dup.update config
102
+ bind_address = config[:BindAddress]
103
+ port = config[:Port]
104
+ processes = config[:Processes]
105
+ config[:Logger] ||= WEBrick::Log.new
106
+
107
+ @listeners = WEBrick::Utils.create_listeners bind_address, port
108
+ if @listeners.first.respond_to? :set_accept_filter then
109
+ @listeners.each do |server|
110
+ server.set_accept_filter 'httpready'
111
+ end
112
+ end
113
+
114
+ pids = []
115
+
116
+ processes.times do
117
+ pids << fork do
118
+ server = self.new config, default
119
+ yield server
120
+ end
121
+ end
122
+
123
+ return pids
124
+ end
125
+
126
+ end
127
+
128
+ ##
129
+ # Only need to override default.
130
+
131
+ def initialize(config = {}, default = WEBrick::Config::HighPerformance)
132
+ super config, default
133
+ end
134
+
135
+ ##
136
+ # HighPerformanceServer doesn't log. Oh you want access logs? Well tough!
137
+
138
+ def access_log(*args)
139
+ end
140
+
141
+ ##
142
+ # Our listeners have already been created, so suck them in from the class.
143
+
144
+ def listen(address, port)
145
+ @listeners = self.class.listeners
146
+ end
147
+
148
+ ##
149
+ # Don't close the listeners, just stop.
150
+
151
+ def shutdown
152
+ stop
153
+ end
154
+
155
+ end
156
+
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11.6
3
+ specification_version: 1
4
+ name: webrick-high-performance
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2006-03-24 00:00:00 -08:00
8
+ summary: A high-performance WEBrick server
9
+ require_paths:
10
+ - lib
11
+ email: eric@robotcoop.com
12
+ homepage:
13
+ rubyforge_project:
14
+ description: A high-performance WEBrick server that takes advantage of sendfile(2) and fork(2) to serve static files really fast.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Eric Hodel
31
+ files:
32
+ - LICENSE
33
+ - Manifest.txt
34
+ - README
35
+ - Rakefile
36
+ - lib/webrick/highperformanceserver.rb
37
+ test_files: []
38
+
39
+ rdoc_options: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ executables: []
44
+
45
+ extensions: []
46
+
47
+ requirements: []
48
+
49
+ dependencies:
50
+ - !ruby/object:Gem::Dependency
51
+ name: socket_sendfile
52
+ version_requirement:
53
+ version_requirements: !ruby/object:Gem::Version::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 1.1.0
58
+ version:
59
+ - !ruby/object:Gem::Dependency
60
+ name: socket_accept_filter
61
+ version_requirement:
62
+ version_requirements: !ruby/object:Gem::Version::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 1.0.0
67
+ version: