<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        text-align:right;
        direction:rtl;
        unicode-bidi:embed;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:36.0pt;
        margin-bottom:0cm;
        margin-left:0cm;
        margin-bottom:.0001pt;
        text-align:right;
        direction:rtl;
        unicode-bidi:embed;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:612.0pt 792.0pt;
        margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
        {page:Section1;}
/* List Definitions */
@list l0
        {mso-list-id:449328036;
        mso-list-type:hybrid;
        mso-list-template-ids:-104421234 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1
        {mso-list-id:648707344;
        mso-list-type:hybrid;
        mso-list-template-ids:221262632 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l1:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2
        {mso-list-id:753472813;
        mso-list-type:hybrid;
        mso-list-template-ids:1100926382 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l2:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l3
        {mso-list-id:1132596488;
        mso-list-type:hybrid;
        mso-list-template-ids:-1815020966 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l3:level1
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
-->
</style>
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="Section1">
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">Hi,</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">Working
with the new version I have encountered some problems which look like memory
leaks to me.</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">I've
written 3 test methods that reproduce the problems, and would appreciate your response.</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">Thanks</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><u>Problem
1</u></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">Occurs
when you do the all of the following</p>
<p class="MsoListParagraph" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left;
text-indent:-18.0pt;mso-list:l2 level1 lfo4;direction:ltr;unicode-bidi:embed"><span style="mso-list:Ignore">1.<span style="font:7.0pt "Times New Roman"">
</span></span><span dir="LTR"></span>Define a generator method</p>
<p class="MsoListParagraph" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left;
text-indent:-18.0pt;mso-list:l2 level1 lfo4;direction:ltr;unicode-bidi:embed"><span style="mso-list:Ignore">2.<span style="font:7.0pt "Times New Roman"">
</span></span><span dir="LTR"></span>Insert a try/except clause in the
method</p>
<p class="MsoListParagraph" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left;
text-indent:-18.0pt;mso-list:l2 level1 lfo4;direction:ltr;unicode-bidi:embed"><span style="mso-list:Ignore">3.<span style="font:7.0pt "Times New Roman"">
</span></span><span dir="LTR"></span>define an inner method that uses
some local variable</p>
<p class="MsoListParagraph" style="mso-margin-top-alt:0cm;margin-right:0cm;
margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left;
text-indent:-18.0pt;mso-list:l2 level1 lfo4;direction:ltr;unicode-bidi:embed"><span style="mso-list:Ignore">4.<span style="font:7.0pt "Times New Roman"">
</span></span><span dir="LTR"></span>Call the generator method without
reaching the "StopIteration"</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">Looks
like the local variable used by the inner method is never cleared.</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">This
code reproduces the problem:</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
def test_generator_memory_leak(self):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
Ipy 2.6 This test reproduces a memory leak when calling a generator method
without reaching the end.</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
coroutine():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
try: pass</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
except: pass</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
just_numbers = range(1,1000)</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
def inner_method():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> return
just_numbers</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
yield None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
yield None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""> </span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> from
System import GC</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
get_memory():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
for _ in xrange(4):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.Collect()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.WaitForPendingFinalizers()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
return GC.GetTotalMemory(True)/1e6</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> before
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> for
j in xrange(10000):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt = coroutine()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt.next()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> after
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> self.assert_(after-before
> 10,'There should be a memory leak in this case.before=%s after=%s' %
(before,after))</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> </p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><u>Problem
2</u></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">The
same as problem, just instead of defining an inner method, just call
"eval" with any string</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
def test_generator_memory_leak2(self):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
Ipy 2.6 This test reproduces a memory leak when calling a generator method
without reaching the end.</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
coroutine(b_bool):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
try: pass</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
except: pass</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
if False: eval("")</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
just_numbers = range(1,1000)</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
yield None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
yield None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""> </span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> from
System import GC</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
get_memory():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
for _ in xrange(4):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.Collect()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.WaitForPendingFinalizers()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
return GC.GetTotalMemory(True)/1e6</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> before
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> for
j in xrange(10000):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt = coroutine(False)</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt.next()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""> </span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> after
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> self.assert_(after-before
> 10,'There should be a memory leak in this case.before=%s after=%s' %
(before,after))</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> </p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"><u>Problem
3</u> </p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">This
is actually a our solution to problems 1,2. We noticed that if we end the
iteration by using "throw" then the memory doesn’t rise on
subsequent instances. Still there some memory increase that depends on the size
of the local variable which doesn’t seem to go away:</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> </p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
def test_generator_memory_leak2(self):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
Ipy 2.6 when exiting a generator method with an exception, some objects are
never collected</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
This seems to be static to the type (the leak does not grow if we repeat the
experiment</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> """<span lang="HE" dir="RTL" style="font-family:"Arial","sans-serif""></span></p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
coroutine():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
just_numbers = range(1,1000000)</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
def inner_method():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> return
just_numbers</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
yield None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
raise Exception("some exception") # comment out this line to make the
test not work</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> from
System import GC</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> def
get_memory():</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
for _ in xrange(4):</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.Collect()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> GC.WaitForPendingFinalizers()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
return GC.GetTotalMemory(True)/1e6</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> before
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> crt
= coroutine()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> try:</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt.next()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
crt.next()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> except:</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed">
pass</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> crt
= None</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> after
= get_memory()</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> self.assert_(after-before
> 10,'There should be a memory leak in this case.before=%s after=%s' % (before,after))</p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> </p>
<p class="MsoNormal" style="text-align:left;direction:ltr;unicode-bidi:embed"> </p>
</div>
</body>
</html>