View mode: basic / threaded / horizontal-split · Log in · Help
February 08, 2009
Old problem with performance
(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;
}
//========================
February 08, 2009
Re: Old problem with performance
Weed wrote:
> [snip]

If I had to take a guess, I'd say that it's six times slower because
you're performing 100 million allocations.  You aren't benchmarking
class/struct overhead, you're benchmarking the overhead of doing 100
million allocations.

You're comparing apples and heffalumps.

 -- Daniel
February 08, 2009
Re: Old problem with performance
Daniel Keep пишет:
> Weed wrote:
>> [snip]
> 
> If I had to take a guess, I'd say that it's six times slower because
> you're performing 100 million allocations.  You aren't benchmarking
> class/struct overhead, you're benchmarking the overhead of doing 100
> million allocations.
> 
> You're comparing apples and heffalumps.

Yes, but problem is that D does not leave  way to create a class
instance without allocation
February 08, 2009
Re: Old problem with performance
Weed пишет:
> Daniel Keep пишет:
>> Weed wrote:
>>> [snip]
>> If I had to take a guess, I'd say that it's six times slower because
>> you're performing 100 million allocations.  You aren't benchmarking
>> class/struct overhead, you're benchmarking the overhead of doing 100
>> million allocations.
>>
>> You're comparing apples and heffalumps.
> 
> Yes, but problem is that D does not leave  way to create a class
> instance without allocation

I should explain that I compare not only structs and classes in D but
also classes in C++, there classes work as fast as well as structures in
case of usage of overload of operators.
February 08, 2009
Re: Old problem with performance
Weed wrote:
> Daniel Keep пишет:
>> Weed wrote:
>>> [snip]
>> If I had to take a guess, I'd say that it's six times slower because
>> you're performing 100 million allocations.  You aren't benchmarking
>> class/struct overhead, you're benchmarking the overhead of doing 100
>> million allocations.
>>
>> You're comparing apples and heffalumps.
> 
> Yes, but problem is that D does not leave  way to create a class
> instance without allocation

You can allocate a class on the stack with:

   scope c = new C();
February 08, 2009
Re: Old problem with performance
Walter Bright wrote:
> Weed wrote:
>> Daniel Keep пишет:
>>> Weed wrote:
>>>> [snip]
>>> If I had to take a guess, I'd say that it's six times slower because
>>> you're performing 100 million allocations.  You aren't benchmarking
>>> class/struct overhead, you're benchmarking the overhead of doing 100
>>> million allocations.
>>>
>>> You're comparing apples and heffalumps.
>>
>> Yes, but problem is that D does not leave  way to create a class
>> instance without allocation
> 
> You can allocate a class on the stack with:
> 
>    scope c = new C();

Which helps (a bit) with the two instances allocated in main(), but is 
rather unhelpful with the 100_000_000 allocated in opAdd() (they're 
returned)...
February 08, 2009
Re: Old problem with performance
On Sun, 08 Feb 2009 10:26:37 +0300, Weed <resume755@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.
February 08, 2009
Re: Old problem with performance
Denis Koroskin пишет:

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

At present in D is not contain support of value types for objects.
(I consider that it is necessary)

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

[skip]

> 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.

+ it is difficult and also it will be even more difficult if it will be
necessary to make support for the construction like:

space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords;

In this example we create a temporary class "path", create temporary
class "checkpoint" and we take coords of checkpoint of this path. It is
not expedient to us to store all this path and checkpoint because it is
vary.

(from
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)
February 08, 2009
Re: Old problem with performance
On Sun, 08 Feb 2009 17:07:31 +0300, Weed <resume755@mail.ru> wrote:

> Denis Koroskin пишет:
>
>> Your C objects have value semantics. For value semantics you should use  
>> value types.
>
> At present in D is not contain support of value types for objects.
> (I consider that it is necessary)
>
>> Alternatively you may want to use the following trick (I used it for  
>> lazy string concatenation in C+):
>
> [skip]
>
>> 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.
>
> + it is difficult and also it will be even more difficult if it will be
> necessary to make support for the construction like:
>
> space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords;
>
> In this example we create a temporary class "path", create temporary
> class "checkpoint" and we take coords of checkpoint of this path. It is
> not expedient to us to store all this path and checkpoint because it is
> vary.
>
> (from
> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)

I believe you should stick with structs for that.
February 08, 2009
Re: Old problem with performance
Denis Koroskin пишет:

>>
>> [skip]
>>
>>> 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.
>>
>> + it is difficult and also it will be even more difficult if it will be
>> necessary to make support for the construction like:
>>
>> space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords;
>>
>> In this example we create a temporary class "path", create temporary
>> class "checkpoint" and we take coords of checkpoint of this path. It is
>> not expedient to us to store all this path and checkpoint because it is
>> vary.
>>
>> (from
>> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)
>>
> 
> I believe you should stick with structs for that.
> 

Let's assume, polymorphism is necessary to these objects
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home