<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 14 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","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.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>I am fairly sure it is no different than when using disposable objects in any .NET application. If you don’t call IDisposable.Dispose() directly (or via the “using()” statement), then those objects will be disposed via their finalizer when the GC collects them. This happens automatically and fairly frequently in a .NET application. Those objects will be cleaned up for you – assuming you really aren’t holding references to them. If you find they never seem to go away, then I highly recommend attaching a memory profiler (SciTech’s MemProfiler is superb) and exploring the heap graph for the root paths that are responsible for pinning them.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Take note that your ScriptScope itself is holding references to all of the objects contained within. You will need to discard all references to that ScriptScope if you want it (and its contents) to be collected by the runtime.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>If you conclude that they truly are eligible for collection, and you just can’t wait for the system to clean up on its own, then you can always call GC.Collect() directly. I really don’t recommend that kind of brute force approach though. There are very few situations where calling GC.Collect() is really the right thing to do.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><b><span style='font-size:14.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Keith Rome<o:p></o:p></span></b></p><p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Senior Consultant and Architect<o:p></o:p></span></b></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>MCPD-EAD, MCSD, MCDBA, MCTS-WPF, MCTS-TFS, MCTS-WSS<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Wintellect | 770.617.4016 | <a href="mailto:rome@wintellect.com">krome@wintellect.com</a><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:10.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><a href="http://www.wintellect.com/">www.wintellect.com</a><o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p><p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> ironpython-users-bounces+rome=wintellect.com@python.org [mailto:ironpython-users-bounces+rome=wintellect.com@python.org] <b>On Behalf Of </b>Igor Brejc<br><b>Sent:</b> Saturday, February 11, 2012 10:11 AM<br><b>To:</b> Dino Viehland<br><b>Cc:</b> Ironpython-users@python.org<br><b>Subject:</b> Re: [Ironpython-users] LightweightScopes and scopes in general<o:p></o:p></span></p><p class=MsoNormal><o:p>&nbsp;</o:p></p><div><p class=MsoNormal>I'm thinking of this scenario: my host application allows users to run their own Py scripts. OK, in the ideal case, their scripts should take care of the disposal of the reserved resources, but a lot of times user will write trail-and-error scripts which will often fail.&nbsp;Is there a mechanism for the host application to somehow track (and possibly dispose) of the stuff that has been allocated in a failed user script? Using SetTrace() or by simply examining the ScriptScope after the script has finished? Or should I simply ignore this?<o:p></o:p></p></div><div><p class=MsoNormal><o:p>&nbsp;</o:p></p></div><div><p class=MsoNormal>I'm wondering how other people who use IronPython as an embedded scripting engine deal with these issues (if at all).<o:p></o:p></p></div><div><p class=MsoNormal><o:p>&nbsp;</o:p></p></div><div><p class=MsoNormal>Thanks,<o:p></o:p></p></div><div><p class=MsoNormal>Igor<o:p></o:p></p></div><p class=MsoNormal><o:p>&nbsp;</o:p></p><div><p class=MsoNormal>On Fri, Feb 10, 2012 at 10:40 PM, Dino Viehland &lt;<a href="mailto:dinov@microsoft.com">dinov@microsoft.com</a>&gt; wrote:<o:p></o:p></p><div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>We won’t call IDispose on them.&nbsp; Usually they’ll follow the pattern of implementing IDisposable + having a finalizer so they will eventually release their resources.&nbsp; Also they can be used with the “with” statement so that their Dispose methods are eagerly called.</span><o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>&nbsp;</span><o:p></o:p></p><div style='border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt'><div><div style='border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> Igor Brejc [mailto:<a href="mailto:igor.brejc@gmail.com" target="_blank">igor.brejc@gmail.com</a>] <br><b>Sent:</b> Friday, February 10, 2012 10:51 AM<br><b>To:</b> Dino Viehland<br><b>Cc:</b> Jeff Hardy; <a href="mailto:Ironpython-users@python.org" target="_blank">Ironpython-users@python.org</a><br><b>Subject:</b> Re: [Ironpython-users] LightweightScopes and scopes in general</span><o:p></o:p></p></div></div><div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>&nbsp;<o:p></o:p></p><p class=MsoNormal style='mso-margin-top-alt:auto;margin-bottom:12.0pt'>&nbsp;<o:p></o:p></p><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>On Fri, Feb 10, 2012 at 7:46 PM, Dino Viehland &lt;<a href="mailto:dinov@microsoft.com" target="_blank">dinov@microsoft.com</a>&gt; wrote:<o:p></o:p></p><div><p class=MsoNormal style='mso-margin-top-alt:auto;margin-bottom:12.0pt'><br><br>Jeff wrote:<br>&gt; I'm taking a stab off the top of my head based on my limited knowledge of the<br>&gt; internals, but I do know that debug code is not collectable.<br>&gt; It's possible that the code itself may be holding references that keep objects<br>&gt; alive longer than expected.<br>&gt;<br>&gt; I believe if you run the code in a separate AppDomain you can unload the<br>&gt; AppDomain and the code will be collected, which should take everything else<br>&gt; with it.<br>&gt;<br>&gt; &gt;<br>&gt; &gt; I've also tried running in the release mode and turning on the<br>&gt; &gt; options[&quot;LightweightScopes&quot;] = true mode, which seems to help. But I<br>&gt; &gt; cannot find any information about what this option actually does and<br>&gt; &gt; what happens with the scope variables in general. Any info would be<br>&gt; appreciated.<br>&gt;<br>&gt; That one I'll have to leave to Dino.<o:p></o:p></p></div><p class=MsoNormal style='mso-margin-top-alt:auto;margin-bottom:12.0pt'>The difference between the different types of scopes just comes down to how<br>we hold onto global variable and call site objects.<br><br>The most efficient way to hold onto these is to use CLR static fields to store the<br>global variables. &nbsp;That allows the CLR to generate a direct access to the field and<br>we can quickly access the global variables. &nbsp;But it comes at the cost of not being<br>able to recover the static fields and leaking the values that are stored in there.<br><br>The light weight scopes store the variables in a field or an array instead of storing<br>them in static fields. &nbsp;To do that we need to pass in the field or close over it and then<br>on each access we need to do the field or array access (and if it's an array access, it<br>needs to be bounds checked). &nbsp;But the end result is that the only thing which is keeping<br>the global variable / call site objects alive are the delegate which implements the<br>ScriptCode. &nbsp;Once the ScriptCode goes away all of those call sites and PythonGlobal<br>objects can be collected.<br><br>So lightweight scopes come at a performance cost, but they are more applicable<br>Where you're actually re-compiling code regularly.<o:p></o:p></p></div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>&nbsp;<o:p></o:p></p><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>Thanks for that explanation, Dino.<o:p></o:p></p></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>&nbsp;<o:p></o:p></p></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>Another question that pops up: what happens with Disposable objects (like files, GDI+ bitmaps etc.) created within the Py scope (if they are not referenced from the outside)?&nbsp;&nbsp; <o:p></o:p></p></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>&nbsp;<o:p></o:p></p></div><div><p class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto'>Igor<o:p></o:p></p></div></div></div></div></div></div></div><p class=MsoNormal><o:p>&nbsp;</o:p></p></div></body></html>