rt_finalize WTFs?

dsimcha dsimcha at yahoo.com
Sun Dec 4 17:46:27 PST 2011


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.

Is there any good reason to keep this code around?


More information about the Digitalmars-d mailing list