2009-11-03 31 views
8

Tôi cần một số trợ giúp tìm giải pháp cho bộ nhớ bị rò rỉ mà tôi đang gặp phải. Tôi có một ứng dụng C# (.NET v3.5) cho phép người dùng chạy các kịch bản IronPython cho mục đích thử nghiệm. Các tập lệnh có thể tải các mô-đun khác nhau từ thư viện chuẩn Python (như được bao gồm trong các tệp nhị phân IronPython). Tuy nhiên, khi tập lệnh hoàn tất, bộ nhớ được cấp cho các mô-đun đã nhập không phải là rác được thu thập. Lặp qua nhiều lần chạy của một tập lệnh (được thực hiện để kiểm tra căng thẳng) khiến hệ thống hết bộ nhớ trong thời gian sử dụng lâu dài.Nhúng IronPython Memory Leak

Đây là phiên bản đơn giản của những gì tôi đang làm.

Script lớp chức năng chính:

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(); 
} 

Một ví dụ 'test.py' kịch bản mà tải các module ngẫu nhiên (thêm ~ 1500 KB bộ nhớ):

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

Một cơ chế vòng lặp đó sẽ khiến hệ thống hết bộ nhớ:

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

Tôi đã thêm phần để không tối ưu hóa quá trình biên dịch dựa trên những gì tôi tìm thấy trong chủ đề this, nhưng rò rỉ bộ nhớ xảy ra theo cả hai cách. Thêm lời gọi rõ ràng vào s.Dispose() cũng không tạo ra sự khác biệt (như mong đợi). Tôi hiện đang sử dụng IronPython 2.0, nhưng tôi cũng đã cố gắng nâng cấp lên IronPython 2.6 RC2 mà không thành công.

Làm cách nào để lấy các mô-đun đã nhập trong tập lệnh IronPython được nhúng vào để thu gom rác như đối tượng .NET thông thường khi công cụ/thời gian chạy script không nằm trong phạm vi?

Trả lời

6

sử dụng sắt Python 2.6 RC 2, và C# 3,5

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(); 
      } 
    } 
} 

và vòng lặp của tôi là

class Program { 
     static void Main(string[] args) { 
      while (true) { 
       var ipy = new IPy(); 
       ipy.run(); 
      } 
     } 
    } 

mức sử dụng bộ nhớ tăng lên khoảng 70.000K, nhưng sau đó tắt.

+0

Vâng, điều này hoạt động tốt với IronPython 2.6 RC2. Nhưng nó không hoạt động với IronPython 2.0.1. Thật không may, 2.6 RC2 đang gặp sự cố khi nhập các biến vào không gian tên chung. Tôi sẽ thử 2.0.3 và đăng kết quả. Cảm ơn sự giúp đỡ cho đến nay :) – cgyDeveloper

+0

2.0.3 cũng không tốt. – cgyDeveloper

4

Bạn đã thử chạy Iron python trong appDomain của chính nó chưa? Python.CreateEngine cho phép bạn vượt qua nó một AppDomain, mà sau đó có thể được dỡ bỏ khi kịch bản hoàn thành.

Hoặc, dựa trên this thảo luận, sử dụng tùy chọn LightweightScopes, như vậy

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

Đơn giản và hiệu quả là giải pháp thay thế, tôi đã bỏ qua điều này. Bằng cách buộc AppDomain không tải, rò rỉ bộ nhớ được kiểm soát (mặc dù tổng số dấu chân của tôi đã tăng lên bằng cách sử dụng một AppDomain). – cgyDeveloper

+0

Câu trả lời hay, nhưng tôi sẽ giữ điều này mở trong một hoặc hai ngày để xem liệu ai đó có một giải pháp có thể khắc phục được vấn đề, vì đây thực sự chỉ là một giải pháp. – cgyDeveloper

+0

LightweightScopes không hoạt động. Dựa trên các cuộc thảo luận bạn liên kết, nó có khả năng chỉ giải quyết vấn đề tải lại một mô-đun trong một kịch bản mà nó đã được tải. Vấn đề của tôi là bộ sưu tập rác không xảy ra khi tập lệnh hoàn tất. Tuy nhiên, tôi sẽ không ngạc nhiên nếu cả hai vấn đề đều có cùng nguyên nhân gốc rễ trong DLR. – cgyDeveloper