[Sbcl-help] Transient classes

7 views
Skip to first unread message

Fredrik Tolf

unread,
Sep 29, 2012, 2:40:26 AM9/29/12
to sbcl...@lists.sourceforge.net
Dear list,

Would it be possible to create a class in such a fashion that it could be
GC'd once all its instances are gone?

I've tried creating a class in a couple of ways that I thought would work,
and then installing a finalizer function on it to show if it were GC'd,
but I can't seem to get them to be GC'd whatever I do, even if I hack away
all the references I've been able to find, including the following
obviously ugly ways:

(let ((test-class (defclass foo (transient) ())))
(finalize test-class #'(lambda () (print "foo")))
(setf (sb-kernel:classoid-cell-pcl-class (sb-kernel:find-classoid-cell 'foo)) nil)
(sb-mop:remove-direct-subclass (find-class 'transient) test-class))

(let ((test-class (make-instance 'standard-class
:name 'bar
:direct-superclasses (list (find-class 'transient)))))
(finalize test-class #'(lambda () (print "bar")))
(assert (null (ignore-errors (find-class 'bar))))
(sb-mop:remove-direct-subclass (find-class 'transient) test-class))

I then run (gc :full t), but get printed neither "foo" nor "bar".

Is it *at all* possible to create classes that can be GC'd, and if it is,
can it be done in a way that is not a horribly ugly hack? (Even better,
can it be done in any way that might even work outisde SBCL?)

--

Fredrik Tolf

------------------------------------------------------------------------------
How fast is your code?
3 out of 4 devs don\\\'t know how their code performs in production.
Find out how slow your code is with AppDynamics Lite.
http://ad.doubleclick.net/clk;262219672;13503038;z?
http://info.appdynamics.com/FreeJavaPerformanceDownload.html
_______________________________________________
Sbcl-help mailing list
Sbcl...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-help

Christophe Rhodes

unread,
Sep 29, 2012, 4:40:07 AM9/29/12
to Fredrik Tolf, sbcl...@lists.sourceforge.net
Fredrik Tolf <fre...@dolda2000.com> writes:

> I've tried creating a class in a couple of ways that I thought would work,
> and then installing a finalizer function on it to show if it were GC'd,
> but I can't seem to get them to be GC'd whatever I do, even if I hack away
> all the references I've been able to find, including the following
> obviously ugly ways:
>
> (let ((test-class (defclass foo (transient) ())))
> (finalize test-class #'(lambda () (print "foo")))
> (setf (sb-kernel:classoid-cell-pcl-class (sb-kernel:find-classoid-cell 'foo)) nil)
> (sb-mop:remove-direct-subclass (find-class 'transient) test-class))

Well, this seems to be nearly there: if I run

(let ((c (let ((test-class (defclass foo (transient) ())))
(finalize test-class #'(lambda () (print "foo")))
(setf (sb-kernel:classoid-cell-pcl-class (sb-kernel:find-classoid-cell 'foo)) nil)
(sb-mop:remove-direct-subclass (find-class 'transient) test-class))))
(dotimes (i 3)
(gc :full t))
(sb-vm::map-referencing-objects #'print :dynamic c))

then I get as output

#<SB-KERNEL:STANDARD-CLASSOID FOO>
(#<STANDARD-CLASS FOO> (24 . #<CLOSURE # {100295C189}>))

The first of these is obvious, I guess: we'd need an extra
(setf (sb-kernel:classoid-pcl-class (sb-kernel:find-classoid 'foo)) nil)
to remove the reference from the classoid (which raises the question of
why the classoid and the classoid-cell both need a reference...

The second is more problematic; I couldn't convince myself that it came
from a real reference, and MAP-REFERENCING-OBJECTS isn't reliable enough
to do a fine dissection (adding the clearing of CLASSOID-PCL-CLASS made
the other printed reference go away). On the other hand, I wasn't
getting the finalization message printed either, so more investigation
is needed.

Cheers,

Christophe

Fredrik Tolf

unread,
Sep 29, 2012, 12:09:17 PM9/29/12
to Christophe Rhodes, sbcl...@lists.sourceforge.net
On Sat, 29 Sep 2012, Christophe Rhodes wrote:
> sb-vm::map-referencing-objects

I didn't know of that function. That's quite a useful debugging tool.
Thanks! :)

> The second is more problematic; I couldn't convince myself that it came
> from a real reference

Indeed; it makes me wonder if the compiler or some other even more basic
part of SBCL keeps some kind of special reference to it, and makes me
wonder if it's even possible to GC classes, and I'm not really competent
enough in SBCL's internal to answer that question myself.

--

Fredrik Tolf

Nikodemus Siivola

unread,
Sep 30, 2012, 7:29:18 AM9/30/12
to Fredrik Tolf, Christophe Rhodes, sbcl...@lists.sourceforge.net
On 29 September 2012 19:09, Fredrik Tolf <fre...@dolda2000.com> wrote:
> On Sat, 29 Sep 2012, Christophe Rhodes wrote:
>> sb-vm::map-referencing-objects

A caveat: it doesn't inspect closures or funcallable instances.

When someone has a moment, re-building it on top of
SB-INTROSPECT:MAP-ROOT would be good.

> Indeed; it makes me wonder if the compiler or some other even more basic
> part of SBCL keeps some kind of special reference to it, and makes me
> wonder if it's even possible to GC classes, and I'm not really competent
> enough in SBCL's internal to answer that question myself.

It should be possible, but it's a bit of a pain right now. Eg. if
you've called methods, their dispatch tables are going to hold
references to the class wrapper.

Cheers,

-- Nikodemus

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://ad.doubleclick.net/clk;258768047;13503038;j?

Fredrik Tolf

unread,
Sep 30, 2012, 2:09:27 PM9/30/12
to Nikodemus Siivola, Christophe Rhodes, sbcl...@lists.sourceforge.net
On Sun, 30 Sep 2012, Nikodemus Siivola wrote:
> On 29 September 2012 19:09, Fredrik Tolf <fre...@dolda2000.com> wrote:
>> Indeed; it makes me wonder if the compiler or some other even more basic
>> part of SBCL keeps some kind of special reference to it, and makes me
>> wonder if it's even possible to GC classes, and I'm not really competent
>> enough in SBCL's internal to answer that question myself.
>
> It should be possible, but it's a bit of a pain right now. Eg. if
> you've called methods, their dispatch tables are going to hold
> references to the class wrapper.

Oh, I see; that seems like quite a bit of pain, indeed.

If I propose, then, such transient classes as a feature request instead,
would that be taken seriously? :)

--

Fredrik Tolf

Nikodemus Siivola

unread,
Sep 30, 2012, 3:40:39 PM9/30/12
to Fredrik Tolf, Christophe Rhodes, sbcl...@lists.sourceforge.net
On 30 September 2012 21:09, Fredrik Tolf <fre...@dolda2000.com> wrote:

>> It should be possible, but it's a bit of a pain right now. Eg. if
>> you've called methods, their dispatch tables are going to hold
>> references to the class wrapper.

I take this back, actually. It seems I misremembered: wrappers point
to classes only though classoids, so nuking references to classes in
classoids should be enough to take care of them. Old wrappers left
over should be harmless and will be dropped from the caches on their
own.

There might be another surprise someone inside PCL, but nothing overly
exciting, I think.

Cheers,

-- Nikodemus

Fredrik Tolf

unread,
Oct 1, 2012, 7:45:36 PM10/1/12
to Nikodemus Siivola, Christophe Rhodes, sbcl...@lists.sourceforge.net
On Sun, 30 Sep 2012, Nikodemus Siivola wrote:
>>> It should be possible, but it's a bit of a pain right now. Eg. if
>>> you've called methods, their dispatch tables are going to hold
>>> references to the class wrapper.
>
> I take this back, actually. It seems I misremembered: wrappers point
> to classes only though classoids, so nuking references to classes in
> classoids should be enough to take care of them. Old wrappers left
> over should be harmless and will be dropped from the caches on their
> own.
>
> There might be another surprise someone inside PCL, but nothing overly
> exciting, I think.

In that case, it remains a good question why I can't get classes GC'd at
all, though. :-)

--

Fredrik Tolf

------------------------------------------------------------------------------
Don't let slow site performance ruin your business. Deploy New Relic APM
Deploy New Relic app performance management and know exactly
what is happening inside your Ruby, Python, PHP, Java, and .NET app
Try New Relic at no cost today and get our sweet Data Nerd shirt too!
http://p.sf.net/sfu/newrelic-dev2dev
Reply all
Reply to author
Forward
0 new messages