rt_finalize WTFs?

Steven Schveighoffer schveiguy at yahoo.com
Mon Dec 5 06:23:33 PST 2011


On Sun, 04 Dec 2011 20:46:27 -0500, dsimcha <dsimcha at yahoo.com> 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.

I think it might be a good idea to move those two operations to the clear  
function.  Currently, clear(obj) simply calls rt_finalize(obj).

It does seem rather strange to have that finally there, why do we care on  
an exception/error that we zero the vptr?  I'd at least put that code up  
where the first WTF is.

But I think we do need to have the reinitialization of the object and  
zeroing of vptr for clear, since it's part of clear's charter.

I'd support any effort to speed up the GC, it's definitely the worst  
offender for performance.  Looks like there's quite a few good ideas in  
this thread.

-Steve


More information about the Digitalmars-d mailing list