September 05, 2012
I rewrote a 3d game I created during my studies with D 2.0 to manual memory mangement. If I'm not studying I'm working in the 3d Engine deparement of Havok. As I needed to pratice manual memory management and did want to get rid of the GC in D for quite some time, I did go through all this effort to create a GC free version of my game.

The results are:

    DMD GC Version: 71 FPS, 14.0 ms frametime
    GDC GC Version: 128.6 FPS, 7.72 ms frametime
    DMD MMM Version: 142.8 FPS, 7.02 ms frametime

GC collection times:

    DMD GC Version: 8.9 ms
    GDC GC Version: 4.1 ms

As you see the manual managed version is twice as fast as the garbage collected one. Even the highly optimized version created with GDC is still slower the the manual memory management.

You can find the full article at:

http://3d.benjamin-thaut.de/?p=20#more-20


Feedback is welcome.

Kind Regards
Benjamin Thaut
September 05, 2012
On 05-09-2012 13:03, Benjamin Thaut wrote:
> I rewrote a 3d game I created during my studies with D 2.0 to manual
> memory mangement. If I'm not studying I'm working in the 3d Engine
> deparement of Havok. As I needed to pratice manual memory management and
> did want to get rid of the GC in D for quite some time, I did go through
> all this effort to create a GC free version of my game.
>
> The results are:
>
>      DMD GC Version: 71 FPS, 14.0 ms frametime
>      GDC GC Version: 128.6 FPS, 7.72 ms frametime
>      DMD MMM Version: 142.8 FPS, 7.02 ms frametime
>
> GC collection times:
>
>      DMD GC Version: 8.9 ms
>      GDC GC Version: 4.1 ms
>
> As you see the manual managed version is twice as fast as the garbage
> collected one. Even the highly optimized version created with GDC is
> still slower the the manual memory management.
>
> You can find the full article at:
>
> http://3d.benjamin-thaut.de/?p=20#more-20
>
>
> Feedback is welcome.
>
> Kind Regards
> Benjamin Thaut

Is source code available anywhere?

Also, I have to point out that programming for a garbage collected runtime is very different from doing manual memory management. The same patterns don't apply, and you optimize in different ways. For instance, when using a GC, it is very recommendable that you allocate up front and use object pooling - and most importantly, don't allocate at all during your render loop.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 05, 2012
Am 05.09.2012 13:10, schrieb Alex Rønne Petersen:
>
> Is source code available anywhere?
>
> Also, I have to point out that programming for a garbage collected
> runtime is very different from doing manual memory management. The same
> patterns don't apply, and you optimize in different ways. For instance,
> when using a GC, it is very recommendable that you allocate up front and
> use object pooling - and most importantly, don't allocate at all during
> your render loop.
>

The sourcecode is not aviable yet, as it is in a repository of my university, but I can zip it and upload the current version if that is wanted. But it currently does only support Windows and does not have any setup instructions yet.

I do object pooling in both versions, as in game developement you usually don't allocate during the frame. But still in the GC version you have the problem that way to many parts of the language allocate and you don't event notice it when using the GC.

Just to clarify, I'm into 3d engine developement since about 7 years now. So I'm not a newcomer to the subject.

Kind Regards
Benjamin Thaut
September 05, 2012
Benjamin Thaut:

> But still in the GC version you have the problem that way to many parts of the language allocate and you don't event notice it when using the GC.

Maybe a compiler-enforced annotation for functions and modules is able to remove this problem in D.

Bye,
bearophile
September 05, 2012
On 05-09-2012 13:19, Benjamin Thaut wrote:
> Am 05.09.2012 13:10, schrieb Alex Rønne Petersen:
>>
>> Is source code available anywhere?
>>
>> Also, I have to point out that programming for a garbage collected
>> runtime is very different from doing manual memory management. The same
>> patterns don't apply, and you optimize in different ways. For instance,
>> when using a GC, it is very recommendable that you allocate up front and
>> use object pooling - and most importantly, don't allocate at all during
>> your render loop.
>>
>
> The sourcecode is not aviable yet, as it is in a repository of my
> university, but I can zip it and upload the current version if that is
> wanted. But it currently does only support Windows and does not have any
> setup instructions yet.
>
> I do object pooling in both versions, as in game developement you
> usually don't allocate during the frame. But still in the GC version you
> have the problem that way to many parts of the language allocate and you
> don't event notice it when using the GC.
>
> Just to clarify, I'm into 3d engine developement since about 7 years
> now. So I'm not a newcomer to the subject.
>
> Kind Regards
> Benjamin Thaut

Sure, I just want to point out that it's a problem with the language (GC allocations being very non-obvious) as opposed to the nature of GC.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 05, 2012
Am 05.09.2012 14:00, schrieb Alex Rønne Petersen:
>
> Sure, I just want to point out that it's a problem with the language (GC
> allocations being very non-obvious) as opposed to the nature of GC.
>

Thats exactly what I want to cause with this post. More effort should be put into the parts of D that currently allocate, but absolutley don't have to. Also the statement "You can use D without a GC" is not quite as easy as the homepage makes it sound.

My favorite hidden allocation so far is:

class A {}
class B : A{}

A a = new A();
B b = new B();

if(a == b) //this will allocate
{
}

Kind Regards
Benjamin Thaut
September 05, 2012
Am 05.09.2012 14:07, schrieb Benjamin Thaut:
> class A {}
> class B : A{}
>
> A a = new A();
> B b = new B();
>
> if(a == b) //this will allocate
> {
> }

Should be:

class A {}
class B : A{}

const(A) a = new A();
const(B) b = new B();

if(a == b) //this will allocate
{
}
September 05, 2012
On 05-09-2012 14:07, Benjamin Thaut wrote:
> Am 05.09.2012 14:00, schrieb Alex Rønne Petersen:
>  >
>> Sure, I just want to point out that it's a problem with the language (GC
>> allocations being very non-obvious) as opposed to the nature of GC.
>>
>
> Thats exactly what I want to cause with this post. More effort should be
> put into the parts of D that currently allocate, but absolutley don't
> have to. Also the statement "You can use D without a GC" is not quite as
> easy as the homepage makes it sound.

Very true. I've often thought we should ship a GC-less druntime in the normal distribution.

>
> My favorite hidden allocation so far is:
>
> class A {}
> class B : A{}
>
> A a = new A();
> B b = new B();
>
> if(a == b) //this will allocate
> {
> }

Where's the catch? From looking in druntime, I don't see where the allocation could occur.

>
> Kind Regards
> Benjamin Thaut

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 05, 2012
On 05-09-2012 13:03, Benjamin Thaut wrote:
> I rewrote a 3d game I created during my studies with D 2.0 to manual
> memory mangement. If I'm not studying I'm working in the 3d Engine
> deparement of Havok. As I needed to pratice manual memory management and
> did want to get rid of the GC in D for quite some time, I did go through
> all this effort to create a GC free version of my game.
>
> The results are:
>
>      DMD GC Version: 71 FPS, 14.0 ms frametime
>      GDC GC Version: 128.6 FPS, 7.72 ms frametime
>      DMD MMM Version: 142.8 FPS, 7.02 ms frametime
>
> GC collection times:
>
>      DMD GC Version: 8.9 ms
>      GDC GC Version: 4.1 ms
>
> As you see the manual managed version is twice as fast as the garbage
> collected one. Even the highly optimized version created with GDC is
> still slower the the manual memory management.
>
> You can find the full article at:
>
> http://3d.benjamin-thaut.de/?p=20#more-20
>
>
> Feedback is welcome.
>
> Kind Regards
> Benjamin Thaut

BTW, your blog post appears to have comparison misspelled.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 05, 2012
Am 05.09.2012 14:14, schrieb Alex Rønne Petersen:
>
> Where's the catch? From looking in druntime, I don't see where the
> allocation could occur.
>

Everything is in object_.d:

    equals_t opEquals(Object lhs, Object rhs)
    {
        if (lhs is rhs)
            return true;
        if (lhs is null || rhs is null)
            return false;
        if (typeid(lhs) == typeid(rhs))
            return lhs.opEquals(rhs);
        return lhs.opEquals(rhs) &&
               rhs.opEquals(lhs);
    }

Will trigger a comparison of the TypeInfo objects with
if (typeid(lhs) == typeid(rhs))

Which will after some function calls trigger opEquals of TypeInfo

    override equals_t opEquals(Object o)
    {
        /* TypeInfo instances are singletons, but duplicates can exist
         * across DLL's. Therefore, comparing for a name match is
         * sufficient.
         */
        if (this is o)
            return true;
        TypeInfo ti = cast(TypeInfo)o;
        return ti && this.toString() == ti.toString();
    }

Then because they are const, TypeInfo_Const.toString() will be called:

    override string toString()
    {
        return cast(string) ("const(" ~ base.toString() ~ ")");
    }

which allocates, due to array concardination.

But this only happens, if they are not of the same type, and if one of them has a storage qualifier.

Kind Regards
Benjamin Thaut

« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10
Top | Discussion index | About this forum | D home