digitalmars.D - Proposal: ClassInfo hasFinalizer field
- dsimcha (28/28) Jun 04 2011 This post was inspired by my recent work optimizing D's garbage
- Walter Bright (2/4) Jun 04 2011 One issue is that if someone derives from a class and adds a finalizer.
- dsimcha (3/4) Jun 04 2011 But when a class is allocated via new, the classinfo for the exact type
- dsimcha (9/10) Jun 04 2011 One issue I did forget, though, is that these "empty" finalizers do
- Robert Jacques (2/13) Jun 04 2011 They shouldn't. Monitors can be shared across objects.
- Steven Schveighoffer (5/19) Jun 06 2011 The destruction actually calls object._d_monitordelete, which uses
- Steven Schveighoffer (10/21) Jun 06 2011 What about this idea:
This post was inspired by my recent work optimizing D's garbage collector and the Port A Benchmark thread. The current implementation of druntime flags **ALL** classes as having finalizers when allocated via the new operator, even if they don't. The GC then calls an empty finalizer pointed to by class's vtable. In certain GC benchmarks, calling all these empty finalizers actually adds up to a substantial (~15-20%) performance penalty. For example, the tree benchmark provided by Bearophile back when I was working on GC optimizations (available at https://github.com/dsimcha/druntime/blob/master/gcBench/tree1.d) runs in about 44-45 seconds on my machine using stock DMD 2.053. It creates tons of tiny class objects with no finalizers. When I temporarily disable calling finalizers in the GC code, the runtime for this benchmark is cut to 36-37 seconds. If this isn't low-hanging fruit, I don't know what is. What we need is to include a hasFinalizer field in ClassInfo that is true iff a class or any of its ancestors has a non-empty finalizer. Then, the finalize flag in the GC can be set on allocating a class using the new operator only if this flag is true. This would save the time spent calling empty finalizers in places where tons of small, finalizer-free classes are allocated, and probably result in a decent speedup. I've filed an enhancement request to get a hasFinalizer field in Classinfo. (http://d.puremagic.com/issues/show_bug.cgi?id=6103) I am not familiar enough with the DMD codebase to do this myself, but I imagine it's a pretty simple enhancement for someone who is. If someone else takes care of the compiler, I'll take care of the corresponding druntime changes.
Jun 04 2011
On 6/4/2011 9:58 AM, dsimcha wrote:The current implementation of druntime flags **ALL** classes as having finalizers when allocated via the new operator, even if they don't.One issue is that if someone derives from a class and adds a finalizer.
Jun 04 2011
On 6/4/2011 11:45 PM, Walter Bright wrote:One issue is that if someone derives from a class and adds a finalizer.But when a class is allocated via new, the classinfo for the exact type being allocated is passed. At least, that's the way I think it works.
Jun 04 2011
On 6/4/2011 11:45 PM, Walter Bright wrote:One issue is that if someone derives from a class and adds a finalizer.One issue I did forget, though, is that these "empty" finalizers do deallocate the object's monitor. (For those not familiar with these details, D classes contain a hidden monitor field that is null initially. When you do synchronized(someClass), the monitor is lazily initialized.) I guess we could get around this by setting the finalize bit in the monitor initialization code rather than upfront, for classes that don't do any other finalization. This would almost always be more efficient than the status quo since very few classes use monitors.
Jun 04 2011
On Sun, 05 Jun 2011 00:28:58 -0400, dsimcha <dsimcha yahoo.com> wrote:On 6/4/2011 11:45 PM, Walter Bright wrote:They shouldn't. Monitors can be shared across objects.One issue is that if someone derives from a class and adds a finalizer.One issue I did forget, though, is that these "empty" finalizers do deallocate the object's monitor. (For those not familiar with these details, D classes contain a hidden monitor field that is null initially. When you do synchronized(someClass), the monitor is lazily initialized.) I guess we could get around this by setting the finalize bit in the monitor initialization code rather than upfront, for classes that don't do any other finalization. This would almost always be more efficient than the status quo since very few classes use monitors.
Jun 04 2011
On Sun, 05 Jun 2011 01:22:30 -0400, Robert Jacques <sandford jhu.edu> wrote:On Sun, 05 Jun 2011 00:28:58 -0400, dsimcha <dsimcha yahoo.com> wrote:The destruction actually calls object._d_monitordelete, which uses reference counting to ensure sanity. -SteveOn 6/4/2011 11:45 PM, Walter Bright wrote:They shouldn't. Monitors can be shared across objects.One issue is that if someone derives from a class and adds a finalizer.One issue I did forget, though, is that these "empty" finalizers do deallocate the object's monitor. (For those not familiar with these details, D classes contain a hidden monitor field that is null initially. When you do synchronized(someClass), the monitor is lazily initialized.) I guess we could get around this by setting the finalize bit in the monitor initialization code rather than upfront, for classes that don't do any other finalization. This would almost always be more efficient than the status quo since very few classes use monitors.
Jun 06 2011
On Sun, 05 Jun 2011 00:28:58 -0400, dsimcha <dsimcha yahoo.com> wrote:On 6/4/2011 11:45 PM, Walter Bright wrote:What about this idea: Store the bit saying whether the class instance has any finalizers in the monitor field. That is, you still set the hasFinalizer bit in the GC block, but you check the monitor area. For example, if the monitor's lsb is set to 1 (not possible for a pointer), then the optimal case of no monitor, no finalizer is registered as true. What is the big slowdown in rt_finalize? The loop moving up the dtors? Or is it simply calling rt_finalize at all? -SteveOne issue is that if someone derives from a class and adds a finalizer.One issue I did forget, though, is that these "empty" finalizers do deallocate the object's monitor. (For those not familiar with these details, D classes contain a hidden monitor field that is null initially. When you do synchronized(someClass), the monitor is lazily initialized.) I guess we could get around this by setting the finalize bit in the monitor initialization code rather than upfront, for classes that don't do any other finalization. This would almost always be more efficient than the status quo since very few classes use monitors.
Jun 06 2011