Mongrel 0.1.1 -- A Fast Ruby Web Server (It Works Now, Maybe

Hi All,

I previously announce Mongrel 0.1.0, but since I released that late
at night it of course had errors. This is just a small announcement
for the fixed source:

http://www.zedshaw.com/downloads/mongrel-0.1.1.tar.bz2

Please grab this one and give it a try.

INSTALL

You can grab the above source and then do:

rake
ruby -Ilib examples/simpletest.rb &
curl http://localhost:3000/test

It should print out “hello!”. Check the source of examples/
simpletest.rb to see how it’s used.

*** It requires Ruby 1.8.4 to work and a C compiler to compile a
small portable extension. ***

WHAT IT IS

Mongrel is a web server I wrote this week that performs much better
than WEBrick (1350 vs 175 req/sec) and only has one small C
extension. I’m looking to make Mongrel the answer to Java’s Tomcat
as a means of hosting Ruby web applications. Feel free to send me
your dreams about a (sort of) Ruby hosting library.

Special thanks to Ezra and Sascha for testing and finding this.

Zed A. Shaw

In future perf comparisons it would be great if you also compare it to
apache and/or lighttpd in a similar setup/situation just to factor out
the specifics of the machine you test it on.

Thanks,

Robert F.

Compiles and run without problems under fedora core4 (with an AMD 800
Mhz 500M Ram)

siege -u http://localhost:3000/test -d1 -r10 -c25

mongrel


Elapsed time: 8.22 secs
Data transferred: 0.00 MB
Response time: 0.01 secs
Transaction rate: 30.41 trans/sec
Concurrency: 0.20
Longest transaction: 0.12
Shortest transaction: 0.00

webwrick


Elapsed time: 10.99 secs
Data transferred: 0.00 MB
Response time: 0.20 secs
Transaction rate: 22.75 trans/sec
Concurrency: 4.53
Longest transaction: 3.17
Shortest transaction: 0.01

Zed S. wrote:

I previously announce Mongrel 0.1.0, but since I released that late
at night it of course had errors. This is just a small announcement
for the fixed source:

http://www.zedshaw.com/downloads/mongrel-0.1.1.tar.bz2

Please grab this one and give it a try.

This is a fantasy come true. Works nicely on Linux. Sensational! An
era has opened.

I got Camping working with `register’, but it needs both SCRIPT_NAME and
PATH_INFO filled properly to work right. In the case of a script
mounted at /blog, a /blog/view request should end up as (following the
traditional CGI ways):

SCRIPT_NAME = /blog
PATH_INFO = /view

Anyway, here’s a crappy postamble for any Camping scripts out there
(none):

if FILE == $0
Camping::Models::Base.establish_connection :adapter => ‘sqlite3’,
:database => ‘blog3.db’
Camping::Models::Base.logger = Logger.new(‘camping.log’)
require ‘mongrel’

class CampingHandler < Mongrel::HttpHandler
    def process(request, response)
        Object.instance_eval do
            remove_const :ENV
            const_set :ENV, request
        end
        ENV['PATH_INFO'] = '/'
        s = response.socket
        def s.<<(str)
            write("HTTP/1.1 200 OK\r\n#{str}")
        end
        Camping.run('', response.socket)
    end
end

h = Mongrel::HttpServer.new("0.0.0.0", "3000")
h.register("/blog", CampingHandler.new)
h.run.join

end

_why

this is my output under Cygwin now:

$ ruby -v
ruby 1.8.3 (2005-09-21) [i386-cygwin]

$ rake
(in /cygdrive/h/Download/Browser/mongrel-0.1.1)
/usr/bin/ruby extconf.rb
checking for main() in -lc… yes
creating Makefile
make
gcc -g -O2 -I. -I/usr/lib/ruby/1.8/i386-cygwin
-I/usr/lib/ruby/1.8/i386-cygwin -I. -c http11.c
gcc -g -O2 -I. -I/usr/lib/ruby/1.8/i386-cygwin
-I/usr/lib/ruby/1.8/i386-cygwin -I. -c http11_parser.c
gcc -shared -s -Wl,–enable-auto-import,–export-all -L"/usr/lib" -o
http11.so http11.o http11_parser.o -lruby -lc -lcrypt
cp ext/http11/http11.so lib
/usr/bin/ruby -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader.rb”
“test/test_http11.rb” “test/test_trie.rb” “te
st/test_ws.rb”
Loaded suite
/usr/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/rake_test_loader
Started
Error result after 6 bytes of 15
.Read 18 string was 18
…Hitting server
.
Finished in 2.048 seconds.

5 tests, 10 assertions, 0 failures, 0 errors

$ ruby -Ilib examples/simpletest.rb &
[1] 4692

$ curl http://localhost:3000/test
hello!

$ ./ab.exe -S -n 3000 http://localhost:3000/test
Concurrency Level: 1
Time taken for tests: 5.656250 seconds
Complete requests: 3000
Failed requests: 0
Write errors: 0
Total transferred: 156000 bytes
HTML transferred: 21000 bytes
Requests per second: 530.39 [#/sec] (mean)
Time per request: 1.885 [ms] (mean)
Time per request: 1.885 [ms] (mean, across all concurrent
requests)
Transfer rate: 26.87 [Kbytes/sec] received

WOW, that is really something for Cygwin (Ruby/Cygwin is really slow).
It
would be nice if there were at least a WEBrick benchmark included, so
one
could make a direct comparison. If you could get Mongrel to be at least
half as fast as lighttpd that would be really something. Than it would
be
an alternative for production.

-Sascha

On Friday 20 January 2006 12:33 pm, Michael Schoen wrote:

Cool stuff. Is the intent that this enables an even more straightforward
approach for running apps (such as a RoR app) than scgi under lighttpd?
Ie., rather than scgi under lighttpd, just use mod_proxy?

Did you read this post, where Mark Mayo wonders why the newer frameworks
haven’t just been using an http interface (and instead have struggled
with fcgi)?

When running IOWA apps under webrick, one can do exactly this. I don’t
do
that for production apps, however, because the performance penalty.
Even
with the socket overhead, Apache or lighttpd with fcgi, or Apache with
mod_ruby are both substantially faster.

If mongrel proves fast enough, though, using a proxy approach would
become a
very viable alternative for production apps.

Kirk H.

I’m planning a better performance comparison in the future, those
metrics were just quick dirty ones to proof the concept.

Zed A. Shaw

Thanks Alciato, it seems to be pretty portable so far, so the
inclusion of the small C extension isn’t such a bad idea.

One thing though–and I’m just picking nits though–Siege is a really
bad tool for performance testing. Try out httperf or even
apachebench since they give much more accurate statistics. Also,
you’ll want to run many more requests. It takes 10000 on my machine
to get a stable performance characteristics.

Anyway, thanks for the feedback and watch for more.

Zed A. Shaw

That’s sweet. Didn’t even think it would go that fast on Cygwin.
Great news as this means there’s an exit strategy for IIS and Win32
people other than SCGI. Now if I can just the win32 version of fork
working I’d be gold.

One thing, could you do the same test against WEBrick using the
examples/webrick_compare.rb script? Just for my info. You’ll need
to > /dev/null the output to make the test more fair.

Zed A. Shaw

Zed,

Cool stuff. Is the intent that this enables an even more straightforward
approach for running apps (such as a RoR app) than scgi under lighttpd?
Ie., rather than scgi under lighttpd, just use mod_proxy?

Did you read this post, where Mark Mayo wonders why the newer frameworks
haven’t just been using an http interface (and instead have struggled
with fcgi)?

http://www.vmunix.com/mark/blog/archives/2006/01/02/fastcgi-scgi-and-apache-background-and-future/

thanks,
Michael

On Jan 20, 2006, at 2:32 PM, why the lucky stiff wrote:

This is a fantasy come true. Works nicely on Linux. Sensational!
An era has opened.

Thanks! Yeah, I’m totally excited about it. I may finally be able
to shut those “performance” whiners up. :slight_smile:

I got Camping working with `register’, but it needs both
SCRIPT_NAME and PATH_INFO filled properly to work right. In the
case of a script mounted at /blog, a /blog/view request should end
up as (following the traditional CGI ways):

Right, I have to work out the interplay of the register function and
how script/path info would work. Also have to CGI convert the
request parameters and a few other niceties. I’m contemplating where
you would register handlers, and you’d be able to say whether it has
to be an exact match, or a partial match. If it’s partial then the
matched part would be the SCRIPT_NAME, the rest PATH_INFO. If it’s
exact then I’m not sure what.

Any suggestions on this would be great. Basically, what would be
your dream URI response scheme?

Zed A. Shaw

On Jan 20, 2006, at 2:33 PM, Michael Schoen wrote:

Zed,

Cool stuff. Is the intent that this enables an even more
straightforward approach for running apps (such as a RoR app) than
scgi under lighttpd? Ie., rather than scgi under lighttpd, just use
mod_proxy?

Yes, the intention is to produce the optimal deployment scenario for
Ruby web applications. A secondary purpose is to prove my
unofficial “Zed’s STFU Performance Razor”:

“All languages are as fast as the fastest language they can access so
STFU.”

:slight_smile:

I’m imagining that if I can get the various web frameworks to run
well and fast under Mongrel, and sprinkle in a few sexy features,
then it’d be the best way to deploy the applications. I’m thinking a
primary concern is performance, followed by ease of deployment, then
management, and finally API simplicity. What’s nice with just plain
HTTP is that there’s already a mountain of support for production
HTTP hosting and deployment technology.

Did you read this post, where Mark Mayo wonders why the newer
frameworks haven’t just been using an http interface (and instead
have struggled with fcgi)?

http://www.vmunix.com/mark/blog/archives/2006/01/02/fastcgi-scgi-
and-apache-background-and-future/

Yeah, I read that post literally as I was building the precursor to
SCGI, and then decided to take the plunge and just do it. The story
goes like this:

  1. Win32 IIS dudes beg me to get SCGI working under IIS.
  2. I like Win32 dudes, hell I love everybody the same (which is very
    little, but it’s equal at least).
  3. I start working on an HTTP->SCGI proxy. I use Ragel to make a
    clean, fast, and correct parser.
  4. madrobby schools me on my parser with his mountain of browsers
    until I get it working better.
  5. I keep asking myself, “Why don’t I just take the parser and make
    a Ruby web server?”
  6. I keep asking this but it doesn’t sink in. I decide to toy with
    the idea. Someone shows me the articl Then I read the above article
    and just do it.
  7. What you have is about 3-4 days later.

So, that’s the semi-official story. What I also have though is a
HTTP parser that I can break out and make into a library. This means
that other languages could possibly pick it up and write their own
similarly fast web servers with minimal effort. Keep your fingers
crossed.

Zed A. Shaw

On Jan 20, 2006, at 4:21 PM, Kirk H. wrote:

haven’t just been using an http interface (and instead have struggled
become a
very viable alternative for production apps.

I’d love to make it flexible enough to work with any framework, but
I’m starting with ruby on rails. If you’ve got some sample code of
how IOWA maybe runs in WEBrick, or suggestions on what you’d need to
get IOWA running, I’d love it.

Zed A. Shaw

Zed-

I'm still getting a timeout error even with the new version. Am I

doing something wrong here?

[email protected]:~/mongrel-0.1.1# rake
(in /home/ez/mongrel-0.1.1)
make
make: Nothing to be done for `all’.
cp ext/http11/http11.so lib
/usr/local/bin/ruby -Ilib:test “/usr/local/lib/ruby/gems/1.8/gems/
rake-0.6.2/lib/rake/rake_test_loader.rb” “test/test_http11.rb” “test/
test_trie.rb” “test/test_ws.rb”
Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-0.6.2/lib/rake/
rake_test_loader
Started
Error result after 6 bytes of 15
.Read 18 string was 18
…Hitting server
E
Finished in 190.974664 seconds.

  1. Error:
    test_simple_server(WSTest):
    Errno::ETIMEDOUT: Connection timed out - connect(2)
    /usr/local/lib/ruby/1.8/net/http.rb:562:in initialize' /usr/local/lib/ruby/1.8/net/http.rb:562:inconnect’
    /usr/local/lib/ruby/1.8/timeout.rb:48:in timeout' /usr/local/lib/ruby/1.8/timeout.rb:76:intimeout’
    /usr/local/lib/ruby/1.8/net/http.rb:562:in connect' /usr/local/lib/ruby/1.8/net/http.rb:555:indo_start’
    /usr/local/lib/ruby/1.8/net/http.rb:544:in start' /usr/local/lib/ruby/1.8/net/http.rb:379:inget_response’
    /usr/local/lib/ruby/1.8/net/http.rb:356:in get' ./test/test_ws.rb:28:intest_simple_server’

5 tests, 8 assertions, 0 failures, 1 errors
rake aborted!
Command failed with status (1): [/usr/local/bin/ruby -Ilib:test "/usr/
local…]

[email protected]:~/mongrel-0.1.1# ruby -v
ruby 1.8.4 (2005-12-24) [i686-linux]

Cheers-
-Ezra Z.
WebMaster
Yakima Herald-Republic Newspaper
http://yakimaherald.com
[email protected]
blog: http://brainspl.at

One thing, could you do the same test against WEBrick using the
examples/webrick_compare.rb script? Just for my info. You’ll need to >
/dev/null the output to make the test more fair.

Alright, here you go.

first Mongrel:

ab.exe -S -n 10000 http://localhost:3000/test
Concurrency Level: 1
Time taken for tests: 19.437500 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 520000 bytes
HTML transferred: 70000 bytes
Requests per second: 514.47 [#/sec] (mean)
Time per request: 1.944 [ms] (mean)
Time per request: 1.944 [ms] (mean, across all concurrent
requests)
Transfer rate: 26.08 [Kbytes/sec] received

and WEBrick started with

$ ruby -Ilib examples/webrick_compare.rb 2&>1 /dev/null &

ab.exe -S -n 10000 http://localhost:4000/test
Concurrency Level: 1
Time taken for tests: 118.62500 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Total transferred: 1730000 bytes
HTML transferred: 60000 bytes
Requests per second: 84.70 [#/sec] (mean)
Time per request: 11.806 [ms] (mean)
Time per request: 11.806 [ms] (mean, across all concurrent
requests)
Transfer rate: 14.31 [Kbytes/sec] received

These results are very promising. I bet if you can manage to make a
native
win32 version the results will double or triple. A 5 times boost will
even
make Cygwin a viable development environment. I suspect that the win32
version will even be fast enough for production.

-Sascha

PS: With output on the Cygwin/WEBrick combo will drop below 10 req/s on
my box.

You didn’t happen to install the previous version did you?
Otherwise, try the examples/simpletest.rb and if that works then it
might be the test bombing for some reason. Others got it working
under Linux, so maybe I’ll try to catch you on IRC (#rubyonrails) and
troubleshoot with you.

Zed A. Shaw

Zed S. [email protected] writes:

Yes, I’m gonna have to really investigate a native win32 one. If
it’s this fast, and the features are there, it’ll be the easiest way
possible. Only thing in win32 that would be missing is basic server
stuff like daemonize and so on.

I think there are tools to run any program as service, so that
shouldn’t be an issue.

Christian N. wrote:

Zed S. [email protected] writes:

Yes, I’m gonna have to really investigate a native win32 one. If
it’s this fast, and the features are there, it’ll be the easiest way
possible. Only thing in win32 that would be missing is basic server
stuff like daemonize and so on.

I think there are tools to run any program as service, so that
shouldn’t be an issue.

Namely the win32-service package by Daniel B.

http://rubyforge.org/projects/win32utils/

-Sascha

On Jan 20, 2006, at 13:31, Zed S. wrote:

Mongrel is a web server I wrote this week that performs much better
than WEBrick (1350 vs 175 req/sec) and only has one small C extension.

Being a sucker for meaningless benchmarks I had to run this as well :))

[Mongrel]
% ruby -v
ruby 1.8.4 (2005-12-24) [powerpc-darwin7.9.0]
% ruby simpletest.rb
% ab -n 10000 http://localhost:3000/test
Requests per second: 660.20 [#/sec] (mean)

(I get a terse “ERROR: Object” from time to time)

[Webrick]
% ruby -v
ruby 1.8.4 (2005-12-24) [powerpc-darwin7.9.0]
% ruby webrick_compare.rb >& /dev/null
% ab -n 10000 http://localhost:4000/test
Requests per second: 37.90 [#/sec] (mean)

Here is something in python:

[Cherrypy][1]
% python -V
Python 2.4.2
% python tut01_helloworld.py
% ab -n 10000 http://localhost:8080/
Requests per second: 164.92 [#/sec] (mean)

And a bit of Lua [2] to round it up:

[LuaWeb][3]
% lua -v
Lua 5.1 Copyright © 1994-2006 Lua.org, PUC-Rio
% lua Test.lua
% ab -n 10000 http://localhost:1080/hello
Requests per second: 948.32 [#/sec] (mean)

Cheers


PA, Onnay Equitursay
http://alt.textdrive.com/

[1] http://www.cherrypy.org/
[2] http://www.lua.org/about.html
[3] http://dev.alt.textdrive.com/browser/LW/

On Jan 21, 2006, at 7:37 AM, Sascha E. wrote:

and WEBrick started with

Requests per second: 84.70 [#/sec] (mean)

That’s great. The performance is consistently better.

These results are very promising. I bet if you can manage to make a
native win32 version the results will double or triple. A 5 times
boost will even make Cygwin a viable development environment. I
suspect that the win32 version will even be fast enough for
production.

Yes, I’m gonna have to really investigate a native win32 one. If
it’s this fast, and the features are there, it’ll be the easiest way
possible. Only thing in win32 that would be missing is basic server
stuff like daemonize and so on.

Thanks for the testing.

Zed A. Shaw

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs