2009-11-03 7 views
8

메모리 누수에 대한 해결책을 찾는 데 도움이 필요합니다. C# 응용 프로그램 (.NET v3.5)을 사용하면 사용자가 테스트 목적으로 IronPython 스크립트를 실행할 수 있습니다. 스크립트는 Python 표준 라이브러리 (IronPython 바이너리에 포함 된 것과 다른 모듈)를로드 할 수 있습니다. 그러나 스크립트가 완료되면 가져온 모듈에 할당 된 메모리는 가비지 수집되지 않습니다. 하나의 스크립트를 여러 번 돌면서 (스트레스 테스트를 위해) 루프를 돌리면 시스템을 장기간 사용할 때 메모리 부족 현상이 발생합니다.IronPython 내장 메모리 누수

여기에 내가하는 일의 단순화 된 버전이 있습니다.

스크립트 클래스의 주요 기능은 :

import random 
print "Random number: %i" % random.randint(1,10) 

루핑 메커니즘이됩니다

public void Run() 
{ 
    // set up iron python runtime engine 
    this.engine = Python.CreateEngine(pyOpts); 
    this.runtime = this.engine.Runtime; 
    this.scope = this.engine.CreateScope(); 

    // compile from file 
    PythonCompilerOptions pco = (PythonCompilerOptions)this.engine.GetCompilerOptions(); 
    pco.Module &= ~ModuleOptions.Optimized; 
    this.script = this.engine.CreateScriptSourceFromFile(this.path).Compile(pco); 

    // run script 
    this.script.Execute(this.scope); 

    // shutdown runtime (run atexit functions that exist) 
    this.runtime.Shutdown(); 
} 

임의의 모듈을로드 예 'test.py'스크립트 (메모리 1천5백킬로바이트 ~ 추가) 시스템에 메모리가 부족한 경우 :

while(1) 
{ 
    Script s = new Script("test.py"); 
    s.Run(); 
    s.Dispose(); 
} 

컴파일을 최적화하지 않기 위해 섹션을 추가했습니다. 내가 this 스레드에서 찾은 것을 기반으로하지만 메모리 누수가 어느 쪽이든 발생합니다. s.Dispose()에 대한 명시 적 호출을 추가하면 아무런 효과가 없습니다 (예상대로). 현재 IronPython 2.0을 사용하고 있지만 IronPython 2.6 RC2 로의 업그레이드도 시도하지 않았습니다.

스크립팅 엔진/런타임이 범위를 벗어날 때 임베디드 IronPython 스크립트의 가져온 모듈을 일반 .NET 객체처럼 가비지 수집하려면 어떻게합니까?

답변

6

RC 2 아이언 파이썬 2.6을 사용하고 C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Scripting.Hosting; 
using IronPython.Hosting; 

namespace IPmemTest { 
    class IPy { 
     private string script = "import random; random.randint(1,10)"; 

     public IPy() { 
     } 

     public void run() { 
      //set up script environment 
      Dictionary<String, Object> options = new Dictionary<string, object>(); 
      options["LightweightScopes"] = true; 
      ScriptEngine engine = Python.CreateEngine(options); 
      ScriptRuntime runtime = engine.Runtime; 
      ScriptScope scope = runtime.CreateScope(); 
      var source = engine.CreateScriptSourceFromString(this.script); 
      var comped = source.Compile(); 
      comped.Execute(scope); 
      runtime.Shutdown(); 
      } 
    } 
} 

3.5 내 루프

class Program { 
     static void Main(string[] args) { 
      while (true) { 
       var ipy = new IPy(); 
       ipy.run(); 
      } 
     } 
    } 
처럼, LightweightScopes 옵션을 사용

메모리 사용량이 약 70,000K로 증가하지만 그 다음으로 떨어집니다.

+0

예, 이것은 IronPython 2.6 RC2에서 잘 작동합니다. 그러나 IronPython 2.0.1에서는 작동하지 않았습니다. 불행하게도, 2.6 RC2는 전역 네임 스페이스에 변수를 가져 오는 데 문제가 있습니다. 나는 2.0.3을 시도하고 결과를 게시 할 것이다. 지금까지 도움을 주셔서 감사합니다 :) – cgyDeveloper

+0

2.0.3도 좋지 않습니다. – cgyDeveloper

4

아이언 파이썬을 자체 appDomain에서 실행 해 보았습니까? Python.CreateEngine을 사용하면 AppDomain을 전달할 수 있으며, AppDomain은 스크립트 완료시 언로드 할 수 있습니다. this 논의를 기반으로

또는, 그래서

Dictionary<String, Object> options = new Dictionary<string, object>(); 
options["LightweightScopes"] = true; 
ScriptEngine engine = Python.CreateEngine(options); 
ScriptRuntime runtime = engine.Runtime; 
+0

간단하고 효과적인 대안으로, 나는 이것을 간과했습니다. AppDomain을 강제로 언로드하면 메모리 누출이 제어됩니다 (AppDomain을 사용하여 전체 사용 공간이 증가했지만). – cgyDeveloper

+0

좋은 답변이지만이 문제를 해결할 수있는 해결책이 있는지 알기 위해 하루 또는 이틀 동안 열어 두어야합니다. 이는 실제로 해결 방법 일뿐입니다. – cgyDeveloper

+0

LightweightScopes가 작동하지 않습니다. 링크 된 토론에 따라 이미로드 된 스크립트 내에서 모듈을 다시로드하는 문제 만 해결할 가능성이 높습니다. 내 문제는 스크립트가 완료 될 때 발생하지 않는 가비지 수집입니다. 그러나 두 가지 문제가 DLR에서 동일한 근본 원인을 가지고 있다면 나는 놀라지 않을 것입니다. – cgyDeveloper