emplace, scope, enforce [Was: Re: Manual...]

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Jul 21 12:16:15 PDT 2010


On 07/21/2010 01:59 PM, Rory Mcguire wrote:
> Dmitry Olshansky wrote:
>
>> now replace the orignal while loop with this:
>> while (i<  N) {
>> auto testObject = Scoped!Test(i, i, i, i, i, i);
>> //assuming we have aforementioned evil function func(Test t),
>> that keeps global reference to t.
>> //fun(testObject); //uncoment to get an compile error - type
>> mismatch
>> testObject.doSomething(i, i, i, i, i, i);
>> testObject.doSomething(i, i, i, i, i, i);
>> testObject.doSomething(i, i, i, i, i, i);
>> testObject.doSomething(i, i, i, i, i, i);
>> i++;
>> }
>
> With your code I `time` reports the below timings on my machine:
> real	0m19.658s
> user	0m19.590s
> sys	0m0.010s
>
> compared to:
> real	0m9.122s
> user	0m9.090s
> sys	0m0.000s
>
> with bearofiles original version. With -O -release its about 4 seconds
> faster for each.

I compiled and ran the tests myself with -O -release -inline and got 
1.95s for Dmitry's implementation and 1.55s for bearophile's.

I optimized Dmitry's implementation in two ways: I replaced the call to 
clear() with a straight call to the destructor and added = void in two 
places to avoid double initialization. I got 1.11s, which significantly 
undercuts the implementation using scope.

Here's the code I used for testing:

struct Scoped(T) {
     ubyte[__traits(classInstanceSize, Test)] _payload = void;
     T getPayload(){
         return cast(T)(_payload.ptr);
     }
     alias getPayload this;

     static Scoped opCall(Args...)(Args args)
     if (is(typeof(T.init.__ctor(args)))) {
         // TODO: should also provide decent error message
         Scoped!T s = void;
         emplace!T(cast(void[])s._payload,args);
         return s;
     }
     ~this() {
         static if (is(typeof(getPayload.__dtor()))) {
             getPayload.__dtor();
         }
     }
}

final class Test { // 32 bytes each instance
     int i1, i2, i3, i4, i5, i6;
     this(int ii1, int ii2, int ii3, int ii4, int ii5, int ii6) {
         this.i1 = ii1;
         this.i2 = ii2;
         this.i3 = ii3;
         this.i4 = ii4;
         this.i5 = ii5;
         this.i6 = ii6;
     }
     void doSomething(int ii1, int ii2, int ii3, int ii4, int ii5, int 
ii6) {
     }
}

void main(string[] args)
{
     enum int N = 10_000_000;
     int i;
     while (i < N) {
         auto testObject = Scoped!Test(i, i, i, i, i, i);
         //scope testObject = new Test(i, i, i, i, i, i);
         testObject.doSomething(i, i, i, i, i, i);
         testObject.doSomething(i, i, i, i, i, i);
         testObject.doSomething(i, i, i, i, i, i);
         testObject.doSomething(i, i, i, i, i, i);
         i++;
     }
}


Andrei


More information about the Digitalmars-d mailing list