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.