Re: Memory leak or flawed garbage collector

*To*: mathgroup at smc.vnet.net*Subject*: [mg120636] Re: Memory leak or flawed garbage collector*From*: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>*Date*: Sun, 31 Jul 2011 23:36:25 -0400 (EDT)*Delivered-to*: l-mathgroup@mail-archive0.wolfram.com*References*: <j0u7mo$fc1$1@smc.vnet.net> <j10l01$os6$1@smc.vnet.net>

On Sun, 31 Jul 2011 12:27:22 +0100, Alexey Popkov <lehin.p at gmail.com> wrote: > "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com> wrote: > news:j10l01$os6$1 at smc.vnet.net... >> Of course, it is quite possible that the references to your symbols >> responsible for their not being garbage-collected are somewhere other >> than >> the DownValues of In or Out, but if you find and remove these, you >> should >> find that the symbols are garbage-collected (unless for some reason they >> have had their Temporary attribute removed during the course of >> execution). If this does not occur after all references have been >> removed, >> then indeed a bug in the garbage collector would indeed be a >> possibility. > > There is a bug in the garbage collector (non-removing unreferenced > temporary > variables with their definitions): > > In[1]:= $HistoryLength=0; > a[b_]:=Module[{c,d},d:=9;d/;b===1]; > Length@Names[$Context<>"*"] > > Out[3]= 6 > > In[4]:= lst=Table[a[1],{1000}]; > Length@Names[$Context<>"*"] > > Out[5]= 1007 > > In[6]:= lst=. > Length@Names[$Context<>"*"] > > Out[7]= 1007 > > In[8]:= Definition@d$999 > > Out[8]= Attributes[d$999]={Temporary} > > d$999:=9 > > > This bug was originally reported in this MathGroup post: > http://forums.wolfram.com/mathgroup/archive/2010/Dec/msg00130.html Interesting. The bug does not manifest itself if Set is used instead of SetDelayed: In[1] := $HistoryLength=0; a[b_]:=Module[{c,d},d=9;d/;b===1]; Length@Names[$Context<>"*"] Out[3] = 6 In[4] := lst=Table[a[1],{1000}]; Length@Names[$Context<>"*"] Out[5] = 7 (* the new one is lst *) One may speculate that this is due to special treatment of delayed values. In a new session: In[1] := $HistoryLength=0; a[b_]:=Module[{c,d},d:=9;d/;b===1]; Length@Names[$Context<>"*"] Out[3] = 6 In[4] := a[1]; Names[$Context<>"*"] Out[5] = {"a", "b", "c", "c$", "d", "d$", "d$539"} In[6] := OwnValues[d$539] Out[6] = {HoldPattern[d$539] :> 9} In[7] := test = 1; OwnValues[test] (* for comparison *) Out[8] = {HoldPattern[test] :> 1} (* immediate values do not look any different to delayed values from this point of view. Delayed values may therefore be distinguished by an internal flag; the fact that the bug is not present for immediate values implies that it is the delayed values rather than the immediate ones that are subject to special treatment. *) So, let us try: In[9] := d$539 =.; Names[$Context <> "*"] Out[10] = {"a", "b", "c", "c$", "d", "d$", "test"} (* the symbol has now been garbage-collected *) From this we may surmise that values are not being cleared for symbols appearing in a Module that have gone out of scope if the delayed flag is set and if they have also been conditionally evaluated. It appears that these values are what is preventing garbage collection; therefore I would consider this as a bug in Module (in that it does not recognise when values have gone out of scope in all cases) rather than in the garbage collector itself. As reported in the original thread, the same behaviour is not evident with Block, which is logically equivalent to Module in this simple case. Block also does not need to create and maintain temporary symbols, and therefore offers better performance than Module; it seems that this kind of lexical scoping is merely emulated in Mathematica, with dynamic scoping fitting more naturally with the language semantics. For these reasons, unless I explicitly require the temporary symbols, I generally prefer Block in most simple cases, or With where lexical scoping is called for.