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:

A Real-World Use of Lift, a Scala Web Application Framework | Lambda the Ultimate

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 Govedo {Home}

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