(do1 nil (= foo (string:n-of 100000 "@_")))
(defop foo req
(let x copy.foo
; I'm defining 'bar just to be sure it's the strings themselves which
; consume the memory.
(do1 nil (= bar (string:n-of 10 "@_")))
(defop bar req
(let x copy.bar
; And here's an op that should really cause a problem.
(do1 nil (= baz (string:n-of 100000 "@_")))
(defop baz req
(let x copy.baz
(push x bazzes)
If I repeatedly request foo, my Racket process's memory usage (Racket 5.0.1 on Windows XP) climbs as high as 50-60 MB, but after another request, it garbage-collects and releases about half the memory. It does reach higher peaks if I keep going, to the point where now it's going up to 120 MB and dropping to 60, but clearly all those strings I'm making are at least eligible for garbage collection, even if the garbage collector lets more and more of them stick around.
So I've seen no evidence of a memory leak yet... but then again, I haven't had an Arc server run for longer than it takes to do poking around like this. Maybe you should try out a more recent version of Racket?
On a side note, I notice you prefix certain things with "(do1 nil", presumably so that it returns nil rather than returning a gigantic string that the REPL will try to print in its entirety. I stick "no:" in front of things for the same purpose. I.e.:
I find this rather handy and thought I'd share it. (On another note, it seems "~" does the same thing as "no:", which I think is not much of an improvement (1 character instead of 3) and probably not worth allocating a whole ssyntax character for.)
Maybe you should try out a more recent version of Racket?
That's a good idea. I'm still using MzScheme 4.2.1. (Although before I go to the trouble, maybe I should skim recent release notes to see if they were supposed to have fixed any memory leak.)
Thanks for doing that test. I just tried again on my case and it got to > 450 MB (90%+ on a 512 machine) without showing signs of GCing! I'll push it even further later to see if it collects; if it does, then maybe I just need to lower a global like threadlimit* if I don't want the entire machine to get consumed.