
Notice DrRacket kinda chugging, which was a bit surprising…

But then looked at the activity monitor (Mac):

Memory leak perhaps? :slightly_smiling_face:

This would have to be an issue below the level of DrRacket. Are you able to replicate this effect? Or do you have an idea about what might be relevant?

I’ve been working with the flomat
package a lot lately, so might be matrices not getting freed by the GC like they should be (it’s an FFI wrapper to BLAS, I think)?

Not sure if that would account for the DrRacket memory # reporting differently (not sure what the DrRacket memory # is actually reporting)

Quick test (from expression section of DrRacket, not declarations): (require flomat)
(zeros 10000 10000)
Ran, it ate ~700 MB of RAM. Clicked “run” (with empty definitions) and then did (collect-garbage)
. DrRacket reports that the memory is feed, but Activity Monitor shows that it clearly is still being used.

Tagging @soegaard2 so he’s aware. I’m not sure if this would be a Racket issue (foreign language issue) or a package issue of not using #:wrap (deallocator)
for matrix freeing

@massung This is definitely flomat
not deallocating the memory.

I made an issue on GitHub. Happy to help solve it, too

It’s in the issue, but using the deallocation wrappers will probably just magically solve it w/ only a couple lines of code. Example of one in one of my wrappers:
https://github.com/massung/racket-csfml/blob/master/graphics.rkt#L73

Let’s track this down.
The function zeros
calls flomat-zeros
.
(define (flomat-zeros m n)
(make-flomat m n 0.0))
The function make-flomat
allocates memory and fills it with zeros. Then wraps it in a flomat
struct.
(define (make-flomat m n [x 0.0])
(define a (alloc-flomat m n))
(define x* (cast (malloc 1 _double 'atomic) _pointer _flomat))
(ptr-set! x* _double (real->double-flonum x))
(if (= x 0.0)
(memset a 0 (* m n) _double)
(cblas_dcopy (* m n) x* 0 a 1))
(flomat m n a m))
The allocation is done by alloc-flomat
.:
(define (alloc-flomat m n)
(if (or (= m 0) (= n 0))
#f ; ~ NULL
(cast (malloc (* m n) _double 'atomic)
_pointer _flomat)))
So … I need to add deallocation to flomat
structs.

Assuming the type is set, perhaps something as simple as:
(define-libc free (_fun _flomat* -> _void) #:wrap (deallocator))
?

(assuming whatever would be correct for define-libc
)

Then Racket will auto call free()
whenever the flomat is being collected, hopefully

The _flomat
is simple a tagged pointer: (define _flomat (_cpointer 'flomat))
But since I use malloc
from ffi
there must a free
function I can use.

https://docs.racket-lang.org/foreign/Allocation_and_Finalization.html#%28def._%28%28lib._ffi%2Funsafe%2Falloc..rkt%29._deallocator%29%29 Might be helpful, too? Been a while since I’ve done Racket FFI

> But since I use malloc from ffi there must a free function I can use. That would be ideal. I mentioned free
only because the code you pasted used malloc
. :wink:


In some modes the allocated memory can be reclaimed by the garbage collector.

'atomic — Allocates memory that can be reclaimed by the garbage collector but is not traced by the garbage collector. The initial content of the memory is unspecified.

For my past usages, I just defined opaque types:
(define-cpointer-type _sfCircleShape*)
And used the library’s allocator/destroy functions for creating/freeing. Not sure if that’s an option for you, though.

Not sure if (define-cpointer-type _flomat*)
is possible in your use-case

If we can get the garbage collector to free the memory automatically, I’d prefer that. But obviously I am missing something.

You’d then change your allocator cast… (cast (malloc (* m n) _double 'atomic) ... -> (cast _flomat* ...)

err.. (cast (malloc ...) _flomat*)

Define the opaque type, update the cast, then add the deallocator wrapper for that type. May “just work”

@soegaard2 I agree that using 'atomic
should already be the right choice and not require an explicit free
.

That’s being proven out w/ tests, too.

Something else is likely going on.

@massung and I experimented with malloc
and it seems a program using (malloc 100000000 _double 'atomic)
behaves the same as the program using zeros
.