Aaron Clauson
2008-Jul-06 02:09 UTC
[Ironruby-core] Memory Leak with Certain Script Exceptions
Hi, I use the IronRuby scripting engine in a long running server process and came across an issue where the memory utilisation of the process started steadily rising in line with a memory leak. The server process is written in C# (no unmanaged code) and I spent a lot of time double checking and profiling the application to try ensure there were no circular references or static lists keeping hold of objects etc. Eventually I started looking at the Ruby script processing and found that when a script threw certain exceptions the memory utilisation on the process would start steadily incrementing. It''s not all exceptions, syntax errors and method missing execeptions seem fine but ArgumentOutOfRange or NullReferenceExceptions exhibit the behaviour. A stack trace of such a call is shown below. I checked the behaviour using the latest version from svn (6 Jul 2008). System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. Parameter name: startIndex at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) at _stub_##44143(Closure , CallSite , CodeContext , Object , Int32 ) at Microsoft.Scripting.Utils.InvokeHelper`6.Invoke(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4) at Microsoft.Scripting.Utils.ReflectedCaller.InvokeInstance(Object instance, Object[] args) at Microsoft.Scripting.Actions.ActionBinder.UpdateSiteAndExecute[T](CodeContext context, CallSite`1 site, Object[] args) at Microsoft.Scripting.Actions.UpdateDelegates.Update2[T0,T1,TRet](CallSite site, CodeContext context, T0 arg0, T1 arg1) at Initialize##44129(Closure , CodeContext ) at Microsoft.Scripting.ScriptCode.Run(CodeContext context, Boolean tryEvaluate) at Microsoft.Scripting.ScriptCode.Run(Scope scope, Boolean tryEvaluate) at Microsoft.Scripting.ScriptCode.Run(Scope scope) at Microsoft.Scripting.SourceUnit.Execute(Scope scope, ErrorSink errorSink) at Microsoft.Scripting.SourceUnit.Execute(Scope scope) at Microsoft.Scripting.Hosting.ScriptScope.Execute(String code) Regards, Aaron -- Posted via http://www.ruby-forum.com/.
Tomas Matousek
2008-Jul-06 06:28 UTC
[Ironruby-core] Memory Leak with Certain Script Exceptions
What does the script look like? BTW: Circular references alone cannot cause memory leak. CRL GC handles them right. Tomas -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Aaron Clauson Sent: Saturday, July 05, 2008 7:10 PM To: ironruby-core at rubyforge.org Subject: [Ironruby-core] Memory Leak with Certain Script Exceptions Hi, I use the IronRuby scripting engine in a long running server process and came across an issue where the memory utilisation of the process started steadily rising in line with a memory leak. The server process is written in C# (no unmanaged code) and I spent a lot of time double checking and profiling the application to try ensure there were no circular references or static lists keeping hold of objects etc. Eventually I started looking at the Ruby script processing and found that when a script threw certain exceptions the memory utilisation on the process would start steadily incrementing. It''s not all exceptions, syntax errors and method missing execeptions seem fine but ArgumentOutOfRange or NullReferenceExceptions exhibit the behaviour. A stack trace of such a call is shown below. I checked the behaviour using the latest version from svn (6 Jul 2008). System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. Parameter name: startIndex at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy) at _stub_##44143(Closure , CallSite , CodeContext , Object , Int32 ) at Microsoft.Scripting.Utils.InvokeHelper`6.Invoke(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4) at Microsoft.Scripting.Utils.ReflectedCaller.InvokeInstance(Object instance, Object[] args) at Microsoft.Scripting.Actions.ActionBinder.UpdateSiteAndExecute[T](CodeContext context, CallSite`1 site, Object[] args) at Microsoft.Scripting.Actions.UpdateDelegates.Update2[T0,T1,TRet](CallSite site, CodeContext context, T0 arg0, T1 arg1) at Initialize##44129(Closure , CodeContext ) at Microsoft.Scripting.ScriptCode.Run(CodeContext context, Boolean tryEvaluate) at Microsoft.Scripting.ScriptCode.Run(Scope scope, Boolean tryEvaluate) at Microsoft.Scripting.ScriptCode.Run(Scope scope) at Microsoft.Scripting.SourceUnit.Execute(Scope scope, ErrorSink errorSink) at Microsoft.Scripting.SourceUnit.Execute(Scope scope) at Microsoft.Scripting.Hosting.ScriptScope.Execute(String code) Regards, Aaron -- Posted via http://www.ruby-forum.com/. _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core
Aaron Clauson
2008-Jul-06 06:45 UTC
[Ironruby-core] Memory Leak with Certain Script Exceptions
Tomas Matousek wrote:> What does the script look like?Hi Tomas, The Ruby script could be a single line such as: sys.DoMethod(1, 2, 3) Where sys is an object from a custom .Net class that has been loaded and executed as: ScriptRuntime scriptRuntime = IronRuby.CreateRuntime(); ScriptScope rubyScope = scriptRuntime.CreateScope("IronRuby"); DialPlanHelper helper = new DialPlanHelper(); rubyScope.SetVariable("sys", helper); rubyScope.Execute("sys.DoMethod(1, 2, 3)"); If the DoMethod is called with the correct parameters it works fine, however if the wrong number of arguments are provided a System.ArgumentOutOfRangeException is thrown and the memory leak occurs. Regards, Aaron -- Posted via http://www.ruby-forum.com/.
Curt Hagenlocher
2008-Jul-07 01:03 UTC
[Ironruby-core] Memory Leak with Certain Script Exceptions
Are you continuously evaluating new bits of Ruby code? Is each execution in its own ScriptScope? In its own ScriptRuntime? -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Aaron Clauson Sent: Saturday, July 05, 2008 11:45 PM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] Memory Leak with Certain Script Exceptions Tomas Matousek wrote:> What does the script look like?Hi Tomas, The Ruby script could be a single line such as: sys.DoMethod(1, 2, 3) Where sys is an object from a custom .Net class that has been loaded and executed as: ScriptRuntime scriptRuntime = IronRuby.CreateRuntime(); ScriptScope rubyScope = scriptRuntime.CreateScope("IronRuby"); DialPlanHelper helper = new DialPlanHelper(); rubyScope.SetVariable("sys", helper); rubyScope.Execute("sys.DoMethod(1, 2, 3)"); If the DoMethod is called with the correct parameters it works fine, however if the wrong number of arguments are provided a System.ArgumentOutOfRangeException is thrown and the memory leak occurs. Regards, Aaron -- Posted via http://www.ruby-forum.com/. _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core
Aaron Clauson
2008-Jul-07 08:23 UTC
[Ironruby-core] Memory Leak with Certain Script Exceptions
Curt Hagenlocher wrote:> Are you continuously evaluating new bits of Ruby code? Is each > execution in its own ScriptScope? In its own ScriptRuntime?Yes pretty much. I have a bunch of users who can all have their own little bit of script (the scripts are used as a dial plan on a SIP Proxy server). At the moment a new runtime and scope is generated on for each call received so the code per call is the equivalent of: ScriptScope rubyScope = null; try { ScriptRuntime scriptRuntime = IronRuby.CreateRuntime(); rubyScope = scriptRuntime.CreateScope("IronRuby"); DialPlanHelper helper = new DialPlanHelper(); rubyScope.SetVariable("sys", helper); rubyScope.Execute(m_dialPlanScript); } finally { rubyScope.RemoveVariable("sys"); rubyScope = null; } I previously has the ScriptRuntime as a static object common across all users thinking that that would make things quicker but since I''ve had the porblems with memory leaking I''ve swapped that to being a local variable as well. The memory leak definitely only happens when the specific exceptions are thrown. I can run 500 scripts containing an exception and increase the process memory by 50MB. Running 500 scripts that don''t generate an exception does not budge the process memory. Thanks, Aaron -- Posted via http://www.ruby-forum.com/.