Old problem with performance

Denis Koroskin 2korden at gmail.com
Sun Feb 8 04:58:23 PST 2009


On Sun, 08 Feb 2009 10:26:37 +0300, Weed <resume755 at mail.ru> wrote:

> (Has started here:
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)
>
> To me still does not give rest performance of classes (in comparison
> with C++ or with D structs)
>
> I still think that it is a serious problem.
>
> Colleagues from our national D forum have asked to show it and I have
> written simple examples on D. I want to share with you too them.
>
> On my computer the code with structure (i.e. object by value) runs in 6
> times faster than a code with a class:
>
> $ time ./struct
>
> real    0m8.515s
> user    0m7.796s
> sys     0m0.016s
> $ time ./class
>
> real    0m52.185s
> user    0m40.543s
> sys     0m0.076s
>
> The code on C++ is also approximately in 6 times faster a code with
> classes on D. (I do not give an example on C++ because classes on C++
> work just as structures in D.)
>
> I think with it it is necessary to do something.
>
>
> Examples code:
>
> //========================
> struct C {
>     int i;
>     real[5] unused; // to prevent returning this object in registers
>
>     C opAdd( C src ) {
>         C ret;
>         ret.i = i + src.i;
>         return ret;
>     }
> }
>
> int main() {
>     C c1;
>     C c2;
>
>     // initialise i by "random" value to prevent compile-time calculation
>     c1.i = cast(int)&c1;
>     c2.i = 0;
>
>     for(int i = 0; i < 50_000_000; ++i)
>         c2 = c1 + c1 + c1;
>
>     return c2.i;
> }
>
> //========================
>
> class C {
>     int i;
>     real[5] unused; // to prevent returning this object in registers
>
>     C opAdd( C src ) {
>         auto ret = new C;
>         ret.i = i + src.i;
>         return ret;
>     }
> }
>
> int main() {
>     auto c1 = new C;
>     auto c2 = new C;
>
>     // initialise i by "random" value to prevent compile-time calculation
>     c1.i = cast(int)&c1;
>     c2.i = 0;
>
>     for(int i = 0; i < 50_000_000; ++i)
>         c2 = c1 + c1 + c1;
>
>     return c2.i;
> }
> //========================

Your C objects have value semantics. For value semantics you should use value types.

Alternatively you may want to use the following trick (I used it for lazy string concatenation in C+):

class C
{
    int value;

    this(int dim)(ref Sum!(dim) sum)
    {
        value = sum.value;
    }

    Sum!(2) opAdd(C other)
    {
        return Sum!(2)(this, other);
    }
}

struct Sum(int dimension)
{
    private C[dimension] objects;

    this(C first, C second)
    {
        objects[0] = first;
        objects[1] = second;
    }

    this(int dim)(ref Sum!(dim) sum1, ref Sum!(dimension-dim) sum2)
    {
        objects[0..dim][] = sum1.objects[];
        objects[dim+1..dimension] = sum2.objects[];
    }

    this(ref Sum!(dimension-1) sum, C obj)
    {
        objects[0..$-1][] = sum.objects[];
        objects[$-1] = obj;
    }

    Sum!(dimension+1) opAdd(C other)
    {
        return Sum!(dimension+1)(this, other);
    }

    Sum!(dimension+otherDimension) opAdd(otherDimension)(Sum!(otherDimension) other)
    {
        return Sum!(dimension+otherDimension)(this, other);
    }

    int value() {
        int value = 0;
        foreach (C c; objects) {
            value += c.value;
        }
        return value;
    }
}

Apparently, it doesn't work at the moment because ctor can't be a template :(
Is there an enhancement request in bugzilla? It prevents this pattern from working.




More information about the Digitalmars-d mailing list