Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm not a fan of Rails myself, but I sympathize with Yehuda's position. The helpers are my #1 gripe with Rails. It really kills productivity to have to dig through all your views for what feels like pet changes.

The one point Yehuda's making I'd dispute is the impact of Arel.

I saw a very early version of Arel back when I was maintaining DataMapper. To be clear, Arel is beautiful code. It's ridiculously well done IMO from an OO stand-point. It's the code I wished I could write in DM.

I didn't use it (or something like it) in DM because I'd been there and seen the consequences. To give the point some context, you might expect NHibernate to impose a 10% overhead on c#. NHibernate is a very complex library, doing a lot more than most (any?) Ruby O/RM. In Ruby, once you get beyond the most trivial examples, you can easily see numbers like 50% overhead, and some queries that would be a cake-walk in .NET are impractical or even impossible in Ruby with constrained resources or service timeouts.

Ruby method dispatch and object instantiation is slow. Damn slow. Ridiculously slow.

The reason DM and now AR perform two-query-eager-loads to avoid JOINs has almost nothing to do with database performance. I doubt many Rubyists really understand or grok what that means. It has everything to do with the instantiation and even simple iteration of a cartesian product in Ruby being infeasibly slow.

Getting back to Arel: It's probably the very best of Rails OO. But that it's introduced some very serious performance regressions is no surprise at all. I said as much to NK and Yehuda when we discussed it during DataMapper 0.9 development.

With Ruby you have to make compromises. Especially in such a critical-loop portion of your stack.

On the other hand, if you're going to stay with AR, then it probably needed to happen sooner or later.

Best of all worlds would have been to drop AR altogether and promote a migration to Sequel for the official Rails O/RM. ;-)



Wow! This is the first I've heard that RoR's ORM is slow. That's it's slow because Ruby is slow, is even more of a shocker.

I'd love to hear some practical limitations that applications using Ruby and NHibernate face when querying data.

Is this slowness a reason that so many no-sql engines seemed to have sprung at the same time as RoR?


It is embarrassingly slow. I did some tests a couple years ago, on ActiveRecord 3.0.pre, and its 20x slower to initialize empty objects (no database access) than DataMapper, or just making empty Ruby objects & hashes.

https://gist.github.com/260280

Edit: Ran it with AR 3.0.7 and 3.1.0.rc4. Granted, this is with a 2-years newer CPU, but 3.0.7 is a huge step up. 3.1 seems to have regressed again, I'll ping tenderlove about it when I see him.

https://gist.github.com/fabfaf1bd8503fbf6d32


Benchmarks on ActiveRecord before the work Aaron did on Arel (which was dropped in in 3.0.x due to the magnitude of the perfect issue/improvement) are not totally relevant today.

There are still some issues, but there is still low-hanging-fruit as well, such as Aaron's work to add prepare statement caching to Rails 3.1


You'd reasonably expect to give up partial updates for prepared statements, and IIRC their performance benefit was fairly marginal anyways.


Ya, that is not acceptable. File a ticket for me (if you haven't already), and I'll fix this.

As a side note, we need to start keeping benchmarks like this and graph over time. We (rails core) should know about regressions like this before the general public.


Of course the ORM is slow! Is there anyone in 2011 who doesn't know this? Why not bite the bullet and learn SQL? Your DBA will thank you.


A 10% performance penalty to get down and dirty with your Domain Model and go all HSQL isn't exactly a big price to pay.

Take a peek at Paul's benchmark. Iterate and instantiated 100K empty objects in 10s. That's crazy. You're talking about something that would probably take 1ms in c#. You're talking about a performance deficit four orders of magnitude large.

Regardless, I think you've entirely missed the point. The point is not that the O/RMs generate inefficient queries. They may not be perfection, but for what you're asking of it, by and large the queries are not the issue. We're talking about raw method-dispatch.

This simple benchmark takes about 600ms on my MacBook Air:

  require 'benchmark'
  puts Benchmark::measure {
    i = 0
    1_000_000.times { |x| i += x }
  }
The same thing takes 1ms in Mono:

  using System;
  using System.Diagnostics;

  namespace dispatch {
    class MainClass	{
      public static void Main (string[] args)	{
        var s = new Stopwatch();
        s.Start();

        var x = 0;
			
        for (int i = 0; i < 1000000; i++) {
          x += i;	
        }
			
        s.Stop();
			
        Console.WriteLine(s.Elapsed.ToString());
      }
    }
  }
(Forgive me, it's been a very long time since I wrote any c#, but this gave me an excuse to try out Mono. :-) )

You could argue that it's not exactly identical code, but it's fairly idiomatic I'd think for each language.

The point is, the sort of performance deficit you carry with Ruby has real consequences. You don't have to dig very deep at all until such concerns are no longer academic. There's financial applications I've worked on in c# doing transaction reporting with 1,000 rows or so per page that would simply put be at a severe handicap under Ruby and it has nothing to do with the RDBMS.

I'm certainly not gonna give Ruby up any time soon. But it's important as a developer to at least be aware of the shape of the box you live in I think.


The Ruby program takes more time because it is not optimised and it also checks for numeric overflow. The following Ruby program

    puts (1 .. 21).inject :*
will output "51090942171709440000". And

    puts (1 .. 21).inject(:*).class
will output "Bignum" because Ruby switches to big numbers when its integer representation is exceeded.


You make a valid point, but I think it's missing the forest. The example I posted actually results in a Fixnum. It's addition, not multiplication.

Simple math operations are an admittedly terrible way to demonstrate the point I was trying to make (method dispatch and object instantiation overhead). Dismiss it, accept it, or dig deeper verify it. :-)


A more literal translation (using lambdas instead of a native for loop):

   using System;
   using System.Diagnostics;

   namespace testspeed
   {
   	public static class Extensions {
   		public delegate void Action();
   		public static void Times (this int numTimes, Action action)
   		{
   			for (var i = 0; i < numTimes; i++) {
   				action ();
   			}
   		}
   	}
   	class MainClass
   	{
   		public static void Main (string[] args)
   		{
   			var sw = Stopwatch.StartNew();
   			var x = 0;
   			1000000.Times (() => x += 1);
			
   			Console.WriteLine ("{0} in {1} ms", x, sw.ElapsedMilliseconds);
			
   			Console.ReadKey ();
   		}
   	}
   }

and it outputs 4 ms. Mono in debug mode on a 3.2 GHz Intel Core i3. For comparison, the parent's ruby code runs in 80ms with Ruby 1.9.2. Big difference, but not quite as bad. I don't know why though?


The mono C# compiler should pre-evaluate the loop and just set x to the computed value. You'd have to look at the bytecode to verify, but i would be shocked if mono didn't do that.

Still, it should take the blink of an eye, not a chin-scratch.


I get that it could, is there a reason you think it actually does?

Either way, nice observation. Interesting.


Here's the same in Java:

  public class dispatch {
    public static void main(String args[]) {
      long s = System.currentTimeMillis();

      int x = 0;
      for(int i = 0; i < 1000000; i++)
        x += i;

      System.out.printf("%d in %d", x, System.currentTimeMillis() - s);
    }
  }
Just for kicks. I'm not a Java developer but I'd like to get decent at it some day in the near future. Feel free to school me. ;-)


I often wish that DM would have replaced AR in Rails 3. Why Sequel?


Because it's simple, it gives you the flexibility of going lower-level easily, supports CPK+FK and I haven't run into any bugs.

It's been very exciting for me. I picked it up in about a day, asked some questions, and am now easily doing things I couldn't before, and it just works.

Did you know Sequel's open bug-list is often at zero open issues?

Tried AR but it blew my mind that after all this time the support for CPK is still MIA? It's not about Opinionation IMO. Sequel has opinions. It also has features though.

DM had a few bugs. I asked about the particular relation I was trying to get working in #datamapper and Jeremy suggested Sequel would do it easily, pointing me to the test for it on github. So I tried it on a whim. And he was right, it worked.

Then I saw the documentation. It's beautiful. Seriously. Makes my eyes water just thinking about it.

That Sequel isn't the default O/RM for everything-Ruby just goes to prove there is no justice, and no Santa Claus. I'm not always 100% in love with the syntax, but the documentation, the support, the features, all that means so much more than wether I get to define properties for my models or not, and it's not obtrusive.

Oh, and disk-space is cheap. I appreciate that Sequel doesn't break itself up into 500 gems. That really annoys me about DM. There's no excuse for that outside of database drivers (and yes, that is absolutely my own fault; but it should get fixed...).


I don't have much experience beyond the basic with Sequel (DataMapper is my drug of choice), but a simple test here shows that require 'sequel' makes my IRB memory consumption jump from 15.2 to 18.6 megabytes, while require 'dm-core' makes it jump from the same 15.2 to 26.6.

Of course it is by no means a scientific or fair comparison, but still makes me wonder.


Best of all worlds would have been to drop AR altogether and promote a migration to Sequel for the official Rails O/RM. ;-)

Indeed. Or decouple the ORM entirely, though that likely removes a key aspect of what Rails is about.

It is, however, what makes Ramaze so appealing. No coupling to any ORM, but there is a community inclination to use Sequel (so you can learn from example and there are people to answer questions).


ORM is decoupled in rails to my knowledge...

there is a default to AR which is easy to overwrite with your ORM of choice (which often provides an ActiveModel interface and further rails integration by installing one extra gem).

tl;dr: providing sane defaults != strong coupling


OK, thanks, my mistake. Not coupled. But still, there is a strong presumption that your app will use a database and wants a database.yml.

The few times I've wanted to just start a Rails app with simple Erb, with models representing data concepts (but not necessarily SQL anything), and evolve out to using a database (if and when needed), have been frustrating.

It's something that has been easy to do in some other frameworks so I tend to see Rails as almost DB-required, if not in fact coupled.


Yeah you can think of rails as requiring a database. You can pretty easily substitute whatever you want at the database level (sqlite3, mysql, postgresql, mongodb, even redis!), but it's the convention that you'll need to store and retrieve data in your webapp. If you don't need to do this (edge case for most of us), then try a different framework like sinatra that isn't accompanied by all the database bloat.

If you're planning on using a DB eventually but don't want to deal with migrations etc. for now, then start with a NoSQL DB like MongoDB (you don't even need to describe your fields, it can be completely dynamic). You can always sub in an RDBMS later on if your design calls for it.


As of rails 3 (was sort of true in 2 as well) you really don't need a database. I've written two rails 3 apps recently that have no database, they're effectively a thin graphical client for a couple of JSON APIs.

Works well, just don't require ActiveRecord and hey presto, your app doesn't have a database (or db rake tasks, etc).


It would never occur to me to write something non data-driven using Rails... because to me Rails is rapid development platform for data-driven webapps.

Interesting that people do though. Any particular reason? What features of Rails did you still use? Seems like an odd use case.


You seem to know very little about Rails 3. But if you think ramaze has a "community", I guess I can understand why.


Teach, don't snark. Snarking only teaches that the teacher is a snark.


Thanks for the thoughtful response.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: