Hi Marcus, On 29 Jun 2013, at 11:12, Marcus Denker <marcus.denker@inria.fr> wrote:
OK, that seems OK.
The reason I was asking was because I wanted to know if this JavaScript bug would hit us as well:
http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.h...
It is slightly more complicated than the basic question of closing over an unreferenced variable though.
I just can't figure out a way to quickly test it in Pharo. I think it is worth looking into.
Yes, we have exactly the same problem.
imagine a method like this:
test | bigObject smallObject |
[bigObject := Array new: 1000000] value. ^[smallObject := 1].
both big and small are escaping variables that are written. This means they are allocated in an Array on the heap (Cog is calling this a TempVector).
There is just one tempVector created per scope, so we will have a tempVector with both smallObject and bigObject inside created for the method. This then is passed to the blocks, which access the temps via the vector.
The bytecode looks like this:
21 <8A 02> push: (Array new: 2) 23 <68> popIntoTemp: 0 24 <10> pushTemp: 0 25 <8F 10 00 07> closureNumCopied: 1 numArgs: 0 bytes 29 to 35 29 <40> pushLit: Array 30 <21> pushConstant: 1000000 31 <CD> send: new: 32 <8D 00 00> storeIntoTemp: 0 inVectorAt: 0 35 <7D> blockReturn 36 <C9> send: value 37 <87> pop 38 <10> pushTemp: 0 39 <8F 10 00 05> closureNumCopied: 1 numArgs: 0 bytes 43 to 47 43 <76> pushConstant: 1 44 <8D 01 00> storeIntoTemp: 1 inVectorAt: 0 47 <7D> blockReturn 48 <7C> returnTop
The closure [smallObject := 1] now, even though not referencing the largeObject, references the tempVector. This tempVector holds on the to large object --> memory is wasted that is not needed.
Back when implementing the SemChecker, I was thinking about this and wondering⦠for sure this can be optimized by allocating multiple arrays per scope, depending on how they are used later. But even then I am sure you can construct strange cases (multiple nested blocks).
And of course allocating 2 Arrays (or more) wastes memory, too.
So this is not a simple problem⦠the question is how much it matters in practice, though.
Marcus
Thanks for the explanation. I am also not sure if this would be a real problem in practice. I guess most code can be rewritten to avoid it. But it is probably a good idea to document this, maybe in a unit test. And who knows, maybe one day we'll have to revisit this. Sven