When Rails speed matters

I’m developing small intranet solution that displays some data from
another internal HTTP server. Using ‘net/http’ I’m getting data via
rails controller action from another server, this works quite well.
Processing data on another server takes approx. 1-2 seconds, what is
fine and acceptable, but now rails application takes 1-2 sec to respond
to the user. As told earlier its no problem(it was expected) but rails
server technology makes things terribly slow when application is used by
many users. One mongrel server can serve just one user at time. This
means that one user(browser) waits 2 seconds until server data
processed, and the rest of the users stay in queue. I can increase
number of mongrels using mongrel cluster, but its not significant
increase in speed e.g. using 4 mongrels in cluster can serve 4 users at
time only. I created similar test app in java and found the very big
speed difference. Java app running on Jboss is multithreaded and can
serve many users simultaneously but rails app(running one mongrel) is
single threaded. When application responsivness is low the difference
is very big when app is accessing by many users.

Is there any other way how to increase responsivness of such application
on Rails?

David M.

On 7-okt-2006, at 18:07, David M. wrote:

Is there any other way how to increase responsivness of such
application
on Rails?

First of all check of you can scrape your data in the background and
process it locally. Then add Mongrel instances and just load-balance
between them.

Julian ‘Julik’ Tarkhanov
please send all personal mail to
me at julik.nl

Have you tried using backgroundrb ?
What you would do is have the initial request to your application start
a new worker in backgroundrb (which lives outside of your
mongrel/fastcgis/whatever). Your rails app then shows a progress page,
and which refreshes every so often. When your worker has finished then
the next progress refresh redirects them to the actual data they want to
look at.
The key thing is that the long running action happens outside of your
mongrel. leaving it free to service other requests.

Fred

I thought about Backgroundrb, but it seems to me like heavy weight
solution for such small app. I’m also just scared of how this
single-thread issue can affect me in other part of application. I know
its not issue for mostly read-only applications like ‘blogs’ or web
sites (with heavy caching), but intranet apps require many serverside
operations many times … I think that conceptual change should appear
for Rails request handling strategy.

David

This has affected us to an extent, our app is mostly internal facing and
the nature of our business is that the content viewed changes a lot and
so on…

One problem you may run into is that if (say) you have 3 mongrels busy
processing a request, with one mongrel free and a fourth request comes
in then the various setups we tried (apache 1.3 + fastcgi, apache 2.x +
mod_proxy_balancer+mongrel) know nothing about that idle mongrel and so
quite often will dispatch the request to one of the mongrels that is
already busy, artificially increasing the response time.

Our solution to this (driven by the fact that are load is slightly
different, we have a mix of fast actions and the odd slow action, and we
wanted to avoid the slow actions from holding up the fast ones) was to
write a customer load balancer (which you can grab at
http://rubyforge.org/scm/?group_id=2236)

Fred

David M. wrote:

Just downloaded HighWire, nice solution but I can see from source it
just handle the queue of used and not used workers to avoid the problem
you described above. But we still have the limited amount of mongrel
instancies what is a bottle neck. To be honest we are too scared that we
are deciding to move project to Java when it is still in early stages.

What is your real-live experience with Rails used for business like
application when many saves & changes occure and caching cannot be used.
We are excited with development speed and smoothness of Rails but
production speed and responsivness are what the customer will see at the
end. And this matters!

Our application matches that closely: we run a sms based question
answering service (www.82ask.com), so we have a bunch of people
answering questions, obviously everyone is working on different
questions (so not much caching), most page loads involve updates to the
database (the response from the user etc…).

Although the ability for a single mongrel to process many requests
simultaneously would be a nice thing, we’ve found that a large enough
pack of mongrels (which to be fair isn’t actually that large) + highwire

  • backgroundrb for long running tasks is enough for us.

I’ve just remembered that we do have a bit where we connect over http to
various services. The approach we took is to have various ruby ‘daemon’
processes that handle all that (although in our case users don’t need to
see the result of the http request). This might be an alternative to
backgroundrb in your case.

So yes, there are some slight rough edges around this sort of stuff, but
in my experience (admittedly not huge, but I can definitely say that
since our transition to rails we’ve never looked back) the problems have
always been solvable, and at the end of the day the benefits we get from
rails easily outweigh the snags we have hit

Fred

Just downloaded HighWire, nice solution but I can see from source it
just handle the queue of used and not used workers to avoid the problem
you described above. But we still have the limited amount of mongrel
instancies what is a bottle neck. To be honest we are too scared that we
are deciding to move project to Java when it is still in early stages.

What is your real-live experience with Rails used for business like
application when many saves & changes occure and caching cannot be used.
We are excited with development speed and smoothness of Rails but
production speed and responsivness are what the customer will see at the
end. And this matters!

David

On Sat, 7 Oct 2006 14:03:12 -0700
Ezra Z. [email protected] wrote:

time. But mongrel itself is multi threaded and perfectly capable of
serving multiple requests at the same time. You just have to write
your own handler for it. Maybe this will get your started:

Damn, I don’t get to answer any questions anymore. You guys are just
too smart.


Zed A. Shaw, MUDCRAP-CE Master Black Belt Sifu

http://mongrel.rubyforge.org/
http://www.lingr.com/room/3yXhqKbfPy8 – Come get help.

Its surely question for someone else but … will JRuby(on Rails) help
with this in future. Will we have Rails application as a WAR which I we
embed to JBoss?

David

On Oct 7, 2006, at 11:58 AM, Frederick C. wrote:

What is your real-live experience with Rails used for business like
application when many saves & changes occure and caching cannot be
used.
We are excited with development speed and smoothness of Rails but
production speed and responsivness are what the customer will see
at the
end. And this matters!

This is also the type of thing where you could write a custom

Mongrel handler class to do this part of your app. Its a bad idea
tying up rails for 2 seconds while doing an http request to another
server precisely because of the rails only dispatches one request at
a time and queues the rest. This happens in mongrel because there is
a big mutex around the rails dispatcher so it only does one req at a
time. But mongrel itself is multi threaded and perfectly capable of
serving multiple requests at the same time. You just have to write
your own handler for it. Maybe this will get your started:

http://brainspl.at/merb.zip

Merb == Mongrel + Erb. Its just a simple mongrel handler that maps
urls to class names that can return erb templates. Very lightweight
but capable of serving 600 dynamic req/sec for those times when you
need it.

A Merb controller looks like this:

class Test < Merb::Controller
template_dir :test

def hello(*names)
# Assign the parameter to an instance variable
@name = names.join(', ')
render
end
end

– Template

Hello, <%= @name %>

Hello, <%= @name %>!

When you run the server.rb and hit http://localhost:4000/test/hello/
david this will call this:

Test.new.hello(‘david’) which will fill out and return the template
to the browser. Since this is not rails, mongrel can serve requests
more then one at a time so its much faster. This is a really
lightweight simple project but you can mount it at a certain url in
your app to integrate it with your rails app.

-Ezra

Maybe this is a stupid question, but would it not be possible for a
single mongrel to use sandboxes to have multiple, completely independant
copies of rails running, so that each one could serve many requests ? Or
would the overhead be too much ?

Fred