rt_finalize WTFs?

Sean Kelly sean at invisibleduck.org
Wed Dec 7 14:43:28 PST 2011


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.


More information about the Digitalmars-d mailing list