Why is D slower than LuaJIT?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Dec 22 20:14:34 PST 2010


On 12/22/10 4:04 PM, Andreas Mayer wrote:
> To see what performance advantage D would give me over using a scripting language, I made a small benchmark. It consists of this code:
>
>>     auto L = iota(0.0, 10000000.0);
>>     auto L2 = map!"a / 2"(L);
>>     auto L3 = map!"a + 2"(L2);
>>     auto V = reduce!"a + b"(L3);
>
> It runs in 281 ms on my computer.
>
> The same code in Lua (using LuaJIT) runs in 23 ms.
>
> That's about 10 times faster. I would have expected D to be faster. Did I do something wrong?
>
> The first Lua version uses a simplified design. I thought maybe that is unfair to ranges, which are more complicated. You could argue ranges have more features and do more work. To make it fair, I made a second Lua version of the above benchmark that emulates ranges. It is still 29 ms fast.
>
> The full D version is here: http://pastebin.com/R5AGHyPx
> The Lua version: http://pastebin.com/Sa7rp6uz
> Lua version that emulates ranges: http://pastebin.com/eAKMSWyr
>
> Could someone help me solving this mystery?
>
> Or is D, unlike I thought, not suitable for high performance computing? What should I do?

I reproduced the problem with a test program as shown below. On my 
machine the D iota runs in 108ms, whereas a baseline using a handwritten 
loop runs in 43 ms.

I then replaced iota's implementation with a simpler one that's a 
forward range. Then the performance became exactly the same as for the 
simple loop.

Andreas, any chance you could run this on your machine and compare it 
with Lua? (I don't have Lua installed.) Thanks!


Andrei

// D version, with std.algorithm
// ~ 281 ms, using dmd 2.051 (dmd -O -release -inline)

import std.algorithm;
import std.stdio;
import std.range;
import std.traits;

struct Iota2(N, S) if (isFloatingPoint!N && isNumeric!S) {
     private N start, end, current;
     private S step;
     this(N start, N end, S step)
     {
         this.start = start;
         this.end = end;
         this.step = step;
         current = start;
     }
     /// Range primitives
     @property bool empty() const { return current >= end; }
     /// Ditto
     @property N front() { return current; }
     /// Ditto
     alias front moveFront;
     /// Ditto
     void popFront()
     {
         assert(!empty);
         current += step;
     }
     @property Iota2 save() { return this; }
}

auto iota2(B, E, S)(B begin, E end, S step)
if (is(typeof((E.init - B.init) + 1 * S.init)))
{
     return Iota2!(CommonType!(Unqual!B, Unqual!E), S)(begin, end, step);
}

void main(string args[]) {
      double result;
      auto limit = 10_000_000.0;
      if (args.length > 1) {
         writeln("iota");
         auto L = iota2(0.0, limit, 1.0);
         result = reduce!"a + b"(L);
     } else {
         writeln("baseline");
         result = 0.0;
         for (double i = 0; i != limit; ++i) {
             result += i;
         }
     }
     writefln("%f", result);
}


More information about the Digitalmars-d mailing list