On Dec 4, 2011, at 5:46 PM, dsimcha wrote:

> I'm at my traditional passtime of trying to speed up D's garbage collector 
> again, and I've stumbled on the fact that rt_finalize is taking up a 
> ridiculous share of the time (~30% of total runtime) on a benchmark where 
> huge numbers of classes **that don't have destructors** are being created and 
> collected.  Here's the code to this function, from lifetime.d:
> 
> extern (C) void rt_finalize(void* p, bool det = true)
> {
>    debug(PRINTF) printf("rt_finalize(p = %p)\n", p);
> 
>    if (p) // not necessary if called from gc
>    {
>        ClassInfo** pc = cast(ClassInfo**)p;
> 
>        if (*pc)
>        {
>            ClassInfo c = **pc;
>            byte[]    w = c.init;
> 
>            try
>            {
>                if (det || collectHandler is null || 
> collectHandler(cast(Object)p))
>                {
>                    do
>                    {
>                        if (c.destructor)
>                        {
>                            fp_t fp = cast(fp_t)c.destructor;
>                            (*fp)(cast(Object)p); // call destructor
>                        }
>                        c = c.base;
>                    } while (c);
>                }
>                if ((cast(void**)p)[1]) // if monitor is not null
>                    _d_monitordelete(cast(Object)p, det);
>                (cast(byte*) p)[0 .. w.length] = w[];  // WTF?
>            }
>            catch (Throwable e)
>            {
>                onFinalizeError(**pc, e);
>            }
>            finally  // WTF?
>            {
>                *pc = null; // zero vptr
>            }
>        }
>    }
> }
> 
> Getting rid of the stuff I've marked with //WTF? comments (namely the finally 
> block and the re-initializing of the memory occupied by the finalized object) 
> speeds things up by ~15% on the benchmark in question.  Why do we care what 
> state the blob of memory is left in after we finalize it?  I can kind of see 
> that we want to clear things if delete/clear was called manually and we want 
> to leave the object in a state that doesn't look valid.  However, this has 
> significant performance costs and IIRC is already done in clear() and delete 
> is supposed to be deprecated.  Furthermore, I'd like to get rid of the 
> finally block entirely, since I assume its presence and the effect on the 
> generated code is causing the slowdown, not the body, which just assigns a 
> pointer.

Now that having multiple in-flight exceptions is actually legal, we can 
probably just throw out the try/catch entirely.  The try/catch and call to 
onFinalizeError is a holdover from when it was effectively illegal to throw 
from a finalizer.

Reply via email to