3 ms·
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. Itera
by ssmoot 15y ago
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.
- ssmoot 15y agoHere'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. ;-)
- Johngibb 15y agoA 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?
- aaronblohowiak 15y agoThe 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.
- ssmoot 15y agoI get that it could, is there a reason you think it actually does? Either way, nice observation. Interesting.
- deleted 15y ago[deleted]
- aaronblohowiak 15y agoI have no first-hand evidence of the behavior of mono, but constant expression elimination is a common compiler optimization.
- wedesoft 15y agoThe 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.
- ssmoot 15y agoYou 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. :-)