[racket-dev] Testing whether a procedure gets collected
Ah. It prints #f for me when I have debugging info turned on in
DrRacket; otherwise I get #<procedure>. Must be inlining keeping it
around or something.
The problem with either finalizers or weak boxes is that neither
provides enough guarantees. Finalizers are never guaranteed to be run. A
weak box may not be the only reference to a procedure value, depending
on what optimizations are done. I'm trying to test something that's
normally not supposed to be observable.
For now, I've got a finalizer on an array procedure that's created at
the beginning of the 1000-line test module, and I test that the
finalizer was run at the end. I've also got a (collect-garbage) and a
(sleep 0) in there. It works... for now, on my machine.
Maybe a weak box containing a random closure would work. Hmm...
On 12/01/2012 06:46 PM, Robby Findler wrote:
> This prints #f for me.
>
> #lang racket
>
> (define (make-box-thing v)
> (make-weak-box (λ (_) v)))
>
> (define bx (make-box-thing 4))
> (collect-garbage)
> (weak-box-value bx)
>
> And I guess that non-closure procedures are held onto by the modules
> they are inside. This program prints #f for me, and it seems to
> confirm that hypothesis.
>
> #lang racket
>
> (define bx
> (parameterize ([current-namespace (make-base-namespace)])
> (eval '(module m racket
> (define bx (make-weak-box (λ (_) 1)))
> (provide bx)))
> (eval '(require 'm))
> (eval 'bx)))
>
> (collect-garbage)
> (weak-box-value bx)
>
> Robby
>
> On Sat, Dec 1, 2012 at 7:30 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>> Honestly, because I was too rushed to try them before I had to leave this
>> morning. :D However, now that I have the chance, I've found that Typed
>> Racket doesn't support them. I can't add support using `required/typed',
>> because `Weak-Box' would have to be a polymorphic type.
>>
>> Also, they don't seem to let go of procedure values. This one's value
>> doesn't ever turn to #f no matter how many times I collect garbage:
>>
>> (define bx (make-weak-box (λ (_) 0)))
>>
>> Thinking it might be because that lambda doesn't create a closure, I tried
>> this:
>>
>> (define (make-box-thing v)
>> (make-weak-box (λ (_) v)))
>>
>> (define bx (make-box-thing 4))
>>
>> But this `bx' doesn't let go of its value, either. I can't help but think
>> I'm missing something really stupid, though.
>>
>> Neil ⊥
>>
>>
>> On 12/01/2012 10:58 AM, Robby Findler wrote:
>>>
>>> How about using a weak box instead?
>>>
>>> Robby
>>>
>>> On Sat, Dec 1, 2012 at 11:45 AM, Neil Toronto <neil.toronto at gmail.com>
>>> wrote:
>>>>
>>>> I'm getting ready to push a change to math/array that fixes a memory
>>>> leak.
>>>> I've devised a test that I think will determine whether an array's
>>>> procedure
>>>> gets collected after the array is made strict, but I don't know whether
>>>> it
>>>> works only by accident. Here it is:
>>>>
>>>>
>>>> (define: collected? : (Boxof Boolean) (box #f))
>>>>
>>>> (define arr
>>>> (let ([proc (λ: ([js : Indexes]) 0)]) ; constant array
>>>> (register-finalizer proc (λ (proc) (set-box! collected? #t)))
>>>> (build-array #() proc)))
>>>>
>>>> (array-strict! arr)
>>>> (collect-garbage)
>>>> (sleep 0) ; give finalizers a chance to run?
>>>> (check-true (unbox collected?))
>>>>
>>>>
>>>> This test passes for me now, but will fail if anyone else tries it. What
>>>> worries me is that (sleep 0) is apparently required, meaning that
>>>> finalizers
>>>> aren't run immediately when garbage is collected.
>>>>
>>>> How can I ensure that the finalizer for `proc' gets run before I test the
>>>> value of `collected?'?
>>>>
>>>> Neil ⊥
>>>> _________________________
>>>> Racket Developers list:
>>>> http://lists.racket-lang.org/dev
>>
>>