Lift = Rails alternative?

Kind of rambling response:

I don't know how much attention this has gotten, but it's occasionally good
to look at places where Rails might be improved. Ok, maybe it's not Rails so
much as Ruby. What posts about lift seem to say are:

- Ruby is slow
- Ruby is big
- Rails is single-threaded

And they conclude that they are getting orders of magnitude better
performance from their fine new tool without sacrificing a bit of programmer
efficiency. Following the thread further, someone suggests that Mongrel is
the problem and someone else throws out the (unchallenged) assertion that
Mongrel is a hack.

Performance is going to be a thorn in Rails' PR image unless 1) it doesn't
matter, we're getting our apps delivered thank-you-very-much; or 2) someone
addresses footprint and concurrency.

I fall into the (1) category. My sites aren't handling slashdot-like traffic
and if they did, I'll betcha I could find a way to scale my Rails app out to
meet the need. However (2) would make Rails an easier sell than it currently
is.

Really, the "yeah, but" complaints about Rails start and stop with:

- Yeah, but it's slow
- Yeah, but it's big
- Yeah, but it's single-threaded
? And maybe yeah, but where's the @#$& IDE/Debugger

None of these things are even slowing my work down other than to cause a
brief delay while I explain to clients why their concerns are outweighed by
the benefits.

Anyhow, has anyone done much thinking about performance?

Joshua Muheim-2 wrote:

Man, something that the Java community STILL hasn’t “gotten” yet is code generation. It’s one of the more powerful features of Rails and yet every Java framework that tries to compete with Rails never even mentions the subject, or has anything of it’s own. Being able to script/generate controller Stuff and getting all my controller, view, and test files made for me is FAR more important than a smaller or equivalent LOC between Rails and some Java framework.

Looking more at their example code, I see that they (Java community) have yet to understand the Principle of Least Surprise. Half of the stuff I’m reading doesn’t make any sense. XmlAndMap? Is that supposed to be their #render? Yes, some of the reason I can’t understand some of what’s there is Scala itself, as I’ve never spent any time with it.

I’ve messed and looked through enough of the newer Java frameworks coming out and nothing comes even close to being as fun to use as Rails. I don’t care about performance; I especially don’t care about single- vs multi-threaded. Rails means I’m writing Ruby, which is right now the most fun language to write in.

Please let me know when a Java framework comes out that doesn’t try to reinvent web programming and just tries to make things easy for once. They’ve yet to learn that simple lesson and until they do, I will be adamantly against anything Java for the web.

Obligatory note: Yes I know lift is in Scala, but looking through the samples I see the Java mentality quite strongly, and thus I talk about Java in my post.

Jason

After a short time I played with Scala I have a feeling it surprises me half as much as Ruby did when I first started to work with it. And when it does, it’s a “wow” surprise :slight_smile:
Regarding Rails vs Lift, there’s definitely a huge difference between the maturity and “completeness” of the two frameworks but if Lift’s community grows enough, this might not be the case in few months…

I don’t thing marking one of those languages and/or frameworks as better and the other as worse has any sence… There are things Ruby could learn from Scala and things Lift could (and I think will) learn from Rails. Let’s make things better :slight_smile:

I agree with some of this. From the standpoint of PoLS, I think Rails does a
great job. However, one of their compelling points is that they were unable
to host their app on commodity servers using Rails and that lift/Tomcat
required about 1/10 the resource.

The issue of multithreading may be a red herring, but consider this: Say you
write an app with keen Ajax live search that hits makes a request about
every .5 seconds (using observe_field). Now you have a scenario where you
will have peaks of 120 req/minute/user. Forget for a moment that people
typically don't type for a whole minute while searching, and consider the
remainder of the scenario. The app is moderately successful and search is so
fun that at peak traffic times, you have 100 users hitting it at the same
time. That's 12,000 requests/minute or 200/second.

Backing out one step, the current one-in-on-out Rails stack will cause the
app to be less responsive because a number of requests will wind up waiting.
I think this is the point. If it were multithreaded, multiple requests could
be serviced by a single stack relatively efficiently.

What do you think?

Jason Roelofs wrote:

I agree with some of this. From the standpoint of PoLS, I think Rails does a
great job. However, one of their compelling points is that they were unable
to host their app on commodity servers using Rails and that lift/Tomcat
required about 1/10 the resource.

I tell people all the time that Rails doesn't have scaling problems, though it
*does* have some efficiency issues, but I've never seen anyone reasonably claim
a 10x difference for typical web applications -vs- Java.

Java may enjoy a 30% advantage in efficiency on a typical web application.

Who is "their" in this discussion?

The issue of multithreading may be a red herring, but consider this:

snip...

Backing out one step, the current one-in-on-out Rails stack will cause the
app to be less responsive because a number of requests will wind up waiting.
I think this is the point. If it were multithreaded, multiple requests could
be serviced by a single stack relatively efficiently.

Where's the bottleneck on the search?

Many applications experience scaling pains somewhere around 200 req/sec, and
it's usually at the database level. Is your search DB based? If so, 200
req/sec may well require DB tuning to get past.

If the search is not DB backed, is it filesystem backed? If so, can your
block devices handle 200 search req/sec?

If you're not limited in either of these, what's the typical search response
time? If your searching is very fast, then your req queues inside Rails may
well be substantially shorter than the TCP/IP latency between your clients
and your hosts, and the wait queue, which is distributed amongst your Rails
backend processes will almost certainly be MUCH shorter than TCP/IP latency.

Is the search response time slow? If so, then running 200 requests in
parallel are likely going to create a gigantic throughput problem in any
case!

It's even possible that total throughput MAY be higher in a less threaded
environment due to lower context switching overhead and thrash at the DB,
block, and processor level.

The bottom line is this: mod_perl had exactly these same issues in the 90s,
and Java people made the same claims against it as they do about Rails.

Yet, Amazon was written to a very large extend in mod_perl, with custom C
code for certain bottlenecks that were traced down over time.

Tom--

This is exactly the discussion I think we should be having. Back a while in
the thread I mentioned Rails is working just fine for me
thank-you-very-much. The "they" referred to in the thread can be seen at:

http://lambda-the-ultimate.org/node/2147

Sorry for the misquote, they claim 20x performance improvement between
lift/Tomcat and Rails/5 Mongrels. They claim a line-for-line port.

IMPORTANT: I, too, am skeptical. The live search example is somewhat
contrived, as it will almost certainly bog down outside the Rails code. So,
how do you think they support this claim?

One thing that does concern me is the memory footprint of
Ruby/Mongrel/Rails. Memory is cheap, but not so cheap that when you rent it
month-to-month you forget completely about it :slight_smile:

The data on this lift port is not as complete as I'd like, and I suspect
it's a YMMV situation. For e.g., did they user the same database? Is the
database connector they used more tuned than the Ruby one? And on and on.

Their argument still boils down to this poignant statement:

"For single request processing, the lift code, running inside Tomcat, ran 4
times faster than the Rails code running inside Mongrel. However, the CPU
utilization was less than 5% in the lift version, where it was 100% of 1 CPU
(on a dual core machine) for the Rails version. For multiple simultaneous
requests being made from multiple machines, we're seeing better than 20x
performance of the lift code versus the Rails code with 5 Mongrel
instances."

Thoughts?

Tom Mornini wrote:

Hi~

Tom--

This is exactly the discussion I think we should be having. Back a while in
the thread I mentioned Rails is working just fine for me
thank-you-very-much. The "they" referred to in the thread can be seen at:

http://lambda-the-ultimate.org/node/2147

Sorry for the misquote, they claim 20x performance improvement between
lift/Tomcat and Rails/5 Mongrels. They claim a line-for-line port.

IMPORTANT: I, too, am skeptical. The live search example is somewhat
contrived, as it will almost certainly bog down outside the Rails code. So,
how do you think they support this claim?

One thing that does concern me is the memory footprint of
Ruby/Mongrel/Rails. Memory is cheap, but not so cheap that when you rent it
month-to-month you forget completely about it :slight_smile:

The data on this lift port is not as complete as I'd like, and I suspect
it's a YMMV situation. For e.g., did they user the same database? Is the
database connector they used more tuned than the Ruby one? And on and on.

Their argument still boils down to this poignant statement:

"For single request processing, the lift code, running inside Tomcat, ran 4
times faster than the Rails code running inside Mongrel. However, the CPU
utilization was less than 5% in the lift version, where it was 100% of 1 CPU
(on a dual core machine) for the Rails version. For multiple simultaneous
requests being made from multiple machines, we're seeing better than 20x
performance of the lift code versus the Rails code with 5 Mongrel
instances."

Thoughts?

  I did some experimenting with trying to make rails a bit more thread safe and ended up writing my own version of an ActionPack type framework in merb. I am able to gain a lot of performance and handle more concurreny in merb because the mime/cgi parsing and route recognition happen in a thread safe manner and there is only a small mutex lock around anywhere framework user code will run , ie controller actions. In rails the mutex lock is larger and all cgi/mime parsing and route recognition happens inside the mutex.

  By having the mutex lock for a shorter amount of time and parsing and routing requests outside of the lock a single merb mongrel process can handle 50-100 concurrent connections in an httperf test where rails can only really handle 1-5 per mongrel. One of these days when I get some free time I'd like to try to apply some of the stuff I learned writing merb to ActionPack.

  But the Rails team made a pragmatic choice in being single threaded/multi process. As a framework writer you don't have much control over what your users write with your framework, so you could go to all this effort to make everything thread safe, but then all the user's code needs to be thread safe too. And with Ruby's fairly poor threading model it is really easy for people to do stuff in a non thread safe manor. By making each request run in it's own locked context, users don't have to worry if their own code is thread safe or not. That being said, Rails could gain better concurrency by moving cgi parsing and route recognition outside of the mutex in the mongrel rails handler and making those things work in a multithreaded way.

Cheers-
-- Ezra Zygmuntowicz-- Lead Rails Evangelist
-- ez@engineyard.com
-- Engine Yard, Serious Rails Hosting
-- (866) 518-YARD (9273)

I get the impression that their 'benchmark' is very contrived.
I didn't spot any source code or objective metrics either.

Some of their statements reflect a certain amount of naive
Rails/Ruby programming. Especially their comment about
test LOC.

Basically they compared an expertly written Lift/Scala app
with a line-byline port of itself in Rails. Thats a rigged game.

That said, Scala sounds plenty interesting to me. Java as
a language isn't really anything special, but Java as a platform
is huge. Compiling directly to *java* bytecode gets you
running everywhere, and being able to leverage existing Java
APIs gets you using a huge amount of really-hard-to-do
stuff like transaction server APIs.

Yes, Lift APIs is not as syntactically elegant as Rails code,
but coming from Java they have made enormous strides
in this regard, you can forgive them for not seeing the
difference. Still, Lift/Scala has jumped up my interest
queue a lot. It would be a shame to discredit it by associating
it with contrived examples.

I actually do get code generation.

it wasn't quoted in the LtU abstract, but I've done 7 commercial Rails
apps. In additional, I've given a number of presentations at Ruby
conferences and meetings about meta-programming. I've even got an
open source project that incorporates metaprogramming and code
generation.

I've also written a whole Java web framework based on dynamic code
generation. See http://web.archive.org/web/20020601080309/www.govedo.com/index.htm

The very nice thing about Scala and Scala's type system is that one
does not need code generation. See my blog post
http://blog.lostlake.org/index.php?/archives/30-Is-currying-functions-with-functions-Meta-programming.html

I get the impression that their 'benchmark' is very contrived.
I didn't spot any source code or objective metrics either.

Because it's a commercial application that is not yet released, I
can't release anything but code snippets (which are part of comments I
posted to the LtU piece.) However, you can see example code in the
lift package that's a reasonable sampling of lift code.

Some of their statements reflect a certain amount of naive
Rails/Ruby programming. Especially their comment about
test LOC.

How so?

Basically they compared an expertly written Lift/Scala app
with a line-byline port of itself in Rails. Thats a rigged game.

I think you misunderstand. The original app was written in Rails. It
was one of the many applications I've written in Rails over the last
20 months. Because we could not get the scalability that we needed
out of Rails (please read my blog post which describes the decision
process http://blog.lostlake.org/index.php?/archives/45-A-real-world-use-of-lift.html)
we decided to try something else. We tried lift. We ported from
Rails to lift.

Put another way, I have given numerous presentations on Rails over the
last 12+ months. I have written 7 commercial Rails apps. While I'm
not DHH or one of the core Rails team, I think I've got a fair amount
of Rails coding skills.

I took a Rails app that I co-wrote with another skilled developer and
ported it to lift. That's the comparison. The only reason that the
game was rigged is that I wrote lift. So, yes, the idioms that I
built into lift are based on the idioms that I use in Rails. They're
also based on the idioms that I used in Seaside (many of Seaside's
idioms are superior to Rails, not the least of which is binding a
closure to a form post so that the controller doesn't have to unpack
parameters that were defined when the form was built.)

Yes, Lift APIs is not as syntactically elegant as Rails code,
but coming from Java they have made enormous strides
in this regard, you can forgive them for not seeing the
difference.

Actually, I came from Ruby/Rails to Scala. I was a Java guy back in
the day, but most of my code and most of my money in the last couple
of years has come from Ruby-based code.

Three months ago, I would have agreed that Ruby code (and Rails code)
looks cleaner than Scala code (see
http://blog.lostlake.org/index.php?/archives/27-5-Things-a-Ruby-developer-needs-to-know-about-Scala.html)
These days I'm not so sure. I'm one of the editors for the Ruport
documentation project, so I still see a fair amount of Ruby of a
frequent basis. The more time I spent with Scala, the more I
appreciate the syntax. But, like many things, this is a personal
preference and it can change over time.

Still, Lift/Scala has jumped up my interest

queue a lot. It would be a shame to discredit it by associating
it with contrived examples.

I hope you have a chance to use lift and give me some feedback.

If you can find ways for me to make lift and its idioms more pleasing
to you, please drop me a line.

Thanks,

David