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

Reply via email to