MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Memory leak or flawed garbage collector

  • To: mathgroup at smc.vnet.net
  • Subject: [mg120678] Re: Memory leak or flawed garbage collector
  • From: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>
  • Date: Wed, 3 Aug 2011 07:07:58 -0400 (EDT)
  • Delivered-to: l-mathgroup@mail-archive0.wolfram.com
  • References: <j0u7mo$fc1$1@smc.vnet.net> <j10l01$os6$1@smc.vnet.net>

On Tue, 02 Aug 2011 12:12:37 +0100, Alexey Popkov <lehin.p at gmail.com>  
wrote:

> "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com> wrote:
> news:j15738$b4a$1 at smc.vnet.net...
>>  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.
>
> Consider the following simple experiment without Module:
>
> In[1]:= $HistoryLength=0;
> a[b_]:=(SetAttributes[d,Temporary];d:=9;d/;b===1);
>
> In[3]:= a[1]
> Out[3]= 9
>
> In[4]:= Definition[d]
> Out[4]= Attributes[d]={Temporary}
>
> d:=9
>
> As you see, the same bug appears without Module. So I think this is a  
> bug in the garbage collector itself.

There is certainly some subtle behaviour going on here. The reason d is  
still around at the end of this is that it appears lexically in the input  
and is thus referred to by a. For example:

In[1] :=
$HistoryLength = 0;
x[y_] := (
    (* to avoid referencing q explicitly *)
    SetAttributes[Evaluate@Symbol["q"], Temporary];
   );

In[3]:=
Names[$Context <> "*"]

Out[3]=
{"x", "y"}

In[4] :=
x[1];
Names[$Context <> "*"]

Out[5] =
{"x", "y"}

So as long as q isn't referred to directly, the garbage collector does its  
job and the symbol is removed immediately. (This is somewhat useless for  
practical purposes however as the symbol is created and destroyed so  
quickly that one cannot do anything with it.) On the other hand, in a new  
session:

In[1] :=
$HistoryLength = 0;
a[b_] := SetAttributes[d, Temporary];

In[3] :=
Names[$Context <> "*"]

Out[3] =
{"a", "b", "d"} (* even though we haven't done anything yet; reference  
count = 1 *)

In[4] :=
a[1];
Names[$Context <> "*"]

Out[4] =
{"a", "b", "d"} (* no change; reference count still 1 *)

In[5] :=
Clear[a];
Names[$Context <> "*"]

Out[6] =
{"a", "b"} (* reference count 0; it's gone *)

So far all is as expected. But, in a new session:

$HistoryLength = 0;
a[b_] := (
    SetAttributes[d, Temporary];
    d := 9
    (* we don't bother with the conditional evaluation *)
   );

In[3] :=
a[1];
Names[$Context <> "*"]

Out[4] =
{"a", "b", "d"} (* still as expected, per above *)

In[5] :=
Clear[a];
Names[$Context <> "*"]

Out[6] =
{"a", "b", "d"} (* ??? *)

In[7] :=
d = 9; (* delayed assignment changed to immediate *)
Names[$Context <> "*"]

Out[8] =
{"a", "b"} (* gone *)

So it seems that the conjectured "delayed flag" set by SetDelayed  
constitutes a reference to the symbol which prevents its being  
garbage-collected. Needless to say this is rather obscure from the user's  
point of view and could be considered a bug on that account, though there  
is presumably a justifiable reason for it. And, of course, you are correct  
that it is nothing to do with Module per se (which merely confuses the  
issue).

> As for Module, I feel that this function is
> essentially top-level, as opposed to Block. Probably it is possible to  
> write full analog of Module in top-level Mathematica code.

Yes, I agree.

>> 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.
>
> Interesting. I agree that Module looks a bit hacky from the point of  
> view of
> the overall design of the system. As Richard Fateman wrote in his 1991  
> year
> paper "A review of Mathematica", Module was introduced in version 2 for
> fixing inconsistent design of Block scoping and scoping in replacement
> rules: defining
> g[x_] := Block[{a}, a = 1 + x]
> and then evaluating g[a] gives $RecursionLimit::"reclim" error instead of
> 1+a. Module solves this problem.

I'm not sure if I would call this "inconsistent". It is inconvenient, and  
perhaps unexpected to the uninitiated, but it seems to me essentially a  
result of mixing together constructs that imply lexical and dynamic  
scoping in a conflicting way. Module is, however, a good solution to the  
difficulties thus encountered.




  • Prev by Date: Re: Poincare section for double pendulum
  • Next by Date: Re: Integrating Interpolating function
  • Previous by thread: Re: Memory leak or flawed garbage collector
  • Next by thread: Re: Memory leak or flawed garbage collector