massung
2022-2-4 18:52:07

Notice DrRacket kinda chugging, which was a bit surprising…


massung
2022-2-4 18:52:30

But then looked at the activity monitor (Mac):


massung
2022-2-4 18:52:39

Memory leak perhaps? :slightly_smiling_face:


mflatt
2022-2-4 18:54:07

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?


massung
2022-2-4 18:56:51

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)?


massung
2022-2-4 18:57:32

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


massung
2022-2-4 19:03:21

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.


massung
2022-2-4 19:06:49

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


soegaard2
2022-2-4 19:10:57

@massung This is definitely flomat not deallocating the memory.


massung
2022-2-4 19:12:38

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


massung
2022-2-4 19:13:50

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


soegaard2
2022-2-4 19:14:08

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.


massung
2022-2-4 19:15:50

Assuming the type is set, perhaps something as simple as:

(define-libc free (_fun _flomat* -> _void) #:wrap (deallocator)) ?


massung
2022-2-4 19:16:03

(assuming whatever would be correct for define-libc)


massung
2022-2-4 19:16:27

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


soegaard2
2022-2-4 19:18:11

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.



massung
2022-2-4 19:19:26

> 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:



soegaard2
2022-2-4 19:20:36

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


soegaard2
2022-2-4 19:20:49

'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.


massung
2022-2-4 19:22:09

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.


massung
2022-2-4 19:22:28

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


soegaard2
2022-2-4 19:23:23

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


massung
2022-2-4 19:23:29

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


massung
2022-2-4 19:24:39

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


massung
2022-2-4 19:25:05

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


mflatt
2022-2-4 20:09:10

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


massung
2022-2-4 20:11:07

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


massung
2022-2-4 20:11:22

Something else is likely going on.


soegaard2
2022-2-4 20:11:46

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