ironpython2
ironpython2 copied to clipboard
Memory leak when importing ctypes
Version 2.7.7 When executing a script from C#, if we create the ScriptEngine object each iteration, we see a large memory leak when importing the ctypes module. If we use the same script, but do not import ctypes, no memory leak. This may be related to issue #114
It appears that a work around to this is to create a single instance of the ScriptEngine and re-use it.
The following code shows the issue:
static void Main(string[] args)
{
IDictionary<string, object> options = new Dictionary<string, object>();
options["LightweightScopes"] = true;
options["MTA"] = true;
Run3(100, @"import sys; sys.path.append(r'W:\Program Files (x86)\IronPython 2.7\Lib'); import ctypes; print 'ctypes loaded'", options);
Console.ReadKey();
Run3(100, @"import sys; sys.path.append(r'W:\Program Files (x86)\IronPython 2.7\Lib'); print 'ctypes not loaded'", options);
Console.ReadKey();
}
public static void Run3(int iterations, string script, IDictionary<string, object> args)
{
//ScriptEngine engine = Python.CreateEngine(args); // creating only a single engine removes the leak
Console.WriteLine($"---Start---");
for (int i = 0; i < iterations; i++)
{
Thread t = new Thread(() =>
{
ScriptEngine engine = Python.CreateEngine(args); // remove this if creating outside of loop
ScriptSource source = engine.CreateScriptSourceFromString(script, SourceCodeKind.File);
CompiledCode cc = source.Compile();
cc.Execute();
Process p = System.Diagnostics.Process.GetCurrentProcess();
Console.WriteLine($"memory: {(p.WorkingSet64 / 1024)}");
engine.Runtime.Shutdown();
});
t.Start();
t.Join();
}
Console.WriteLine($"---end---");
}
The issue sounds familiar but I can't seem to find where I've seen it before. I don't think the issue is specific to ctypes but occurs with most module imports.
Although we don't import many modules, we've only found the issue when using ctypes. I'm sure you're correct that it happens to more than just ctypes.
For the work around, does anyone know if "engine.Runtime.Shutdown()" sets the engine to its initial state? If we're going to reuse the engine between executions, we want to make sure all previous variables/objects are cleared out.
No, as far as I can tell Shutdown
does not set the engine to its initial state, it performs a shutdown. If you want your executions to be "independent" of each other you can try executing you code in different scopes:
var scope = engine.CreateScope();
cc.Execute(scope);