From: Jason Nielsen
Subject: Porting some code
Date: 
Message-ID: <Pine.SOC.4.63.0804131420080.3997@stawlmihq>
I am trying to port some lispworks code to sbcl.  In several places the 
following form is called:

(hcl:sweep-all-objects (lambda (x) .... ))

that applies the lambda to all live objects in the image.  Does sbcl have 
any equivalent function or even a way of getting a list/vector of the 
objects in the image?

Thanks,
Jason

From: Kent M Pitman
Subject: Re: Porting some code
Date: 
Message-ID: <u8wzh9skv.fsf@nhplace.com>
Jason Nielsen <···@cs.sfu.ca> writes:

> I am trying to port some lispworks code to sbcl.  In several places
> the following form is called:
> 
> (hcl:sweep-all-objects (lambda (x) .... ))
> 
> that applies the lambda to all live objects in the image.  Does sbcl
> have any equivalent function or even a way of getting a list/vector of
> the objects in the image?

Wow.  What a scary function.  What is your application using it for?
From: Jason Nielsen
Subject: Re: Porting some code
Date: 
Message-ID: <Pine.SOC.4.63.0804140613530.16317@stawlmihq>
On Sun, 13 Apr 2008, Kent M Pitman wrote:
>
> Wow.  What a scary function.  What is your application using it for?
>

Indeed.  I didn't write it... just trying to port it ;-)!  Basically the 
code searches for objects of a certain type (of all objects), then checks 
a few slots of the objects it is looking for and decides whether to set 
the object to active/unactive for instance.  Things were going so well 
with minimal changes until I hit this snag.... c'est la vie!

Jason
From: Thomas F. Burdick
Subject: Re: Porting some code
Date: 
Message-ID: <0c169b3d-b8ac-4b40-ae59-ccc0a554abd1@k10g2000prm.googlegroups.com>
On Apr 13, 11:27 pm, Jason Nielsen <····@cs.sfu.ca> wrote:
> I am trying to port some lispworks code to sbcl.  In several places the
> following form is called:
>
> (hcl:sweep-all-objects (lambda (x) .... ))
>
> that applies the lambda to all live objects in the image.  Does sbcl have
> any equivalent function or even a way of getting a list/vector of the
> objects in the image?

Yikes!

If you're willing to hook into the guts of room's implementation, you
could use:

(defun sweep-all-objects (fun)
  (dolist (space '(:static :dynamic :read-only))
    (sb-vm::map-allocated-objects
     (lambda (obj type size)
       (declare (ignore type size))
       (funcall fun obj))
     space)))

But maybe you'd be better off changing the application to take a more
reasonable tack.
From: Jason Nielsen
Subject: Re: Porting some code
Date: 
Message-ID: <Pine.SOC.4.63.0804140830190.16935@stawlmihq>
> Yikes!
>
> If you're willing to hook into the guts of room's implementation, you
> could use:
>
> (defun sweep-all-objects (fun)
>  (dolist (space '(:static :dynamic :read-only))
>    (sb-vm::map-allocated-objects
>     (lambda (obj type size)
>       (declare (ignore type size))
>       (funcall fun obj))
>     space)))
>
> But maybe you'd be better off changing the application to take a more
> reasonable tack.

Not a bad suggestion but my goal at present is to get this code working. 
I'll worry about everything else if I can get that far.  I just took a 
look at the map-allocated-objects function in room.lisp in the sbcl source 
tree..... yikes is right!

Thanks for your help,
Jason
From: Ari Johnson
Subject: Re: Porting some code
Date: 
Message-ID: <m21w57brla.fsf@hermes.theari.com>
Jason Nielsen <···@cs.sfu.ca> writes:

>> Yikes!
>>
>> If you're willing to hook into the guts of room's implementation, you
>> could use:
>>
>> (defun sweep-all-objects (fun)
>>  (dolist (space '(:static :dynamic :read-only))
>>    (sb-vm::map-allocated-objects
>>     (lambda (obj type size)
>>       (declare (ignore type size))
>>       (funcall fun obj))
>>     space)))
>>
>> But maybe you'd be better off changing the application to take a more
>> reasonable tack.
>
> Not a bad suggestion but my goal at present is to get this code
> working. I'll worry about everything else if I can get that far.  I
> just took a look at the map-allocated-objects function in room.lisp in
> the sbcl source tree..... yikes is right!
>
> Thanks for your help,
> Jason

I saw this thread and thought it'd be an interesting experiment. :)

Just so you know, with SBCL 0.9.16 on Linux/amd64:

(defun sweep-all-objects (fun)
  (dolist (space '(:static :dynamic :read-only))
    (sb-vm::map-allocated-objects
     (lambda (obj type size)
       (declare (ignore type size))
       (funcall fun obj))
     space)))
(defparameter *count* 0)
(sweep-all-objects #'(lambda (x) (declare (ignore x)) (incf *count*)))
*count* => 989351

Enjoy!
From: Duane Rettig
Subject: Re: Porting some code
Date: 
Message-ID: <o0iqyke421.fsf@gemini.franz.com>
Jason Nielsen <···@cs.sfu.ca> writes:

> I am trying to port some lispworks code to sbcl.  In several places
> the following form is called:
>
> (hcl:sweep-all-objects (lambda (x) .... ))
>
> that applies the lambda to all live objects in the image.  Does sbcl
> have any equivalent function or even a way of getting a list/vector of
> the objects in the image?

This is of course implementation dependent.  We find in Allegro CL
that most people don't want _all_ objects, but instead objects of a
certain underlying implementation type (and of course, one can iterate
over multiple of these types, if desired, but I seldom see this done).
I've described our version in a couple of talks I've given at ILCs and
the like; our function is simply called #'excl::get-objects.  It takes
one argument, which is the numeric 1-of-256 type code which
corresponds to the implementational type of the object (these codes
are also listed in the middle of a (room t) output).  The function
returns a "heap-walker reasult vector", which has a count as the first
element and then that many actual elements after it.  It runs very
quickly, and has the advantage over any mapping functionalities that
it is taking a snapshot of the entire heap, so you're less likely to
lose items as if you try to process items one at a time - doing so in
the lisp heap that you're trying to measure can have a Heisenberg
effect, especially on newer objects.   But since our heap-walker uses
the same mechanism as our gc, it has in essence no effect on the heap
while it is operating, so you get an accurate snapshot at a particular
time.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: jayessay
Subject: Re: Porting some code
Date: 
Message-ID: <m3iqyg7eih.fsf@sirius.goldenthreadtech.com>
Duane Rettig <·····@franz.com> writes:

> the like; our function is simply called #'excl::get-objects.  It takes
> one argument, which is the numeric 1-of-256 type code which
> corresponds to the implementational type of the object (these codes
> are also listed in the middle of a (room t) output).

Is this thing described in any public documentation?  I don't see it
in the 8* index information.

Also, requesting the arguments for it, ACL says it takes three
arguments:

(type &key old new)

Are the old and new booleans? That restrict the output to just new
space or old spaces?

It's a bit of a cut with an ax capability, but I can see where you
could build some very useful finer grained machinery with it.  And,
indeed, if I'd known about this before, I could have made an aspect or
two of my high speed persistent node store simpler.  Then again, that
would also introduce a pretty low level dependency...

Thanks for the info.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Duane Rettig
Subject: Re: Porting some code
Date: 
Message-ID: <o0ve2guwgb.fsf@gemini.franz.com>
jayessay <······@foo.com> writes:

> Duane Rettig <·····@franz.com> writes:
>
>> the like; our function is simply called #'excl::get-objects.  It takes
>> one argument, which is the numeric 1-of-256 type code which
>> corresponds to the implementational type of the object (these codes
>> are also listed in the middle of a (room t) output).
>
> Is this thing described in any public documentation?  I don't see it
> in the 8* index information.

No, we don't document this and the other major heap-walker function,
called excl::get-references (it populates the result with all of the
objects which have a direct reference to the given lisp object).  From
time to time, I mention these, especially in tutorials I give on
performance, but the reason we don't document the functions is because
they tend to get messy - especially excl::get-references.  Talk about
a Heisenberg effect; every query creates a new array which becomes a
statistic for the next operation... very messy.

> Also, requesting the arguments for it, ACL says it takes three
> arguments:
>
> (type &key old new)
>
> Are the old and new booleans? That restrict the output to just new
> space or old spaces?

Yes on all counts.

> It's a bit of a cut with an ax capability, but I can see where you
> could build some very useful finer grained machinery with it.

A very big ax, and although it tends to be very fast, you would not be
able to get away from touching all pages in your heap if you use it,
which might disrupt your working set.  Presumably that is not a
problem if your heap can be contained in memory, but be sure of the
consequences of your customers having 20 Gb projects and only 2 Gb
memory.  So I would definitely not call it finer-grained...

> And,
> indeed, if I'd known about this before, I could have made an aspect or
> two of my high speed persistent node store simpler.  Then again, that
> would also introduce a pretty low level dependency...

Right; both must be considered.

> Thanks for the info.

No problem.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182