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