2017-01-09 109 views
0

我有一個應用程序,我使用大量的CSharpScript實例來控制應用程序。我面臨的問題是內存使用情況在很大程度上取決於我使用的是什麼類型的全局對象。如果全局類型是在我的應用程序集(巨大程序集)中定義的,則每個編譯腳本的內存使用量將增加約100MB。如果我把全局類型放在一個單獨的程序集中,我發現每個腳本的內存使用量增加了〜10MB,這對於我正在使用的腳本數量仍然有很大的影響。使用CSharpScript接口限制內存使用量

當使用CSharpScript API時,有什麼方法可以限制這種內存使用情況嗎?

回答

1

我相信這裏發生的事情是您的腳本直接引用主應用程序中定義的對象。由於腳本編譯爲單獨的AppDomain,因此AppDomain會從主應用程序的AppDomain中提取自己的本地副本。由於您有100個腳本,每個腳本都有自己的AppDomain,因此您的主要組件會被加載100次。

一種避免這種情況的方法是讓腳本和應用程序之間的任何接口都通過一個「填充」對象,該填充對象是一個小類,在其自己的程序集中定義,可以跨該AppDomain邊界「序列化」數據。 Shim類應繼承MarshalByReferenceObject。這可能會非常棘手和複雜,因爲填充程序無法通過應用程序中定義的任何類,或者像以前一樣「吸入」主程序集。一切都必須作爲.NET中定義的類來傳遞。

作爲基類的MarshalByReferenceObject允許墊片穿過域邊界而不需要整個程序集的副本。

而不是使用又大又重的全局對象的數據給你的腳本:更多信息可以在 https://msdn.microsoft.com/en-us/library/system.marshalbyrefobject(v=vs.110).aspx#Remarks

+0

我試過這個,在一個單獨的程序集中使用非常薄的全局類肯定會造成很大的差異,但我仍然看到每個腳本實例的內存使用量大約爲10MB。很多,如果你有大量的腳本,一個改進,但不是我的情況下的解決方案。 – Chrille

+1

您可以通過循環「AppDomain.Current.Assemblies」來檢查是否有任何額外的程序集被拉入到AppDomain中。如果您的主應用程序出現任何內容,您可以直接參考某些需要刪除的內容才能使其正常工作。 –

0

我不知道什麼是您的具體實現,但有可能爲你做這個發現,可以讓腳本給你的應用程序只有自己的邏輯:

,而不是這個CSX文件,用HeavyObject全球:

// script.csx: 
HeavyObject.DoSomeWork(); 

,你可以這樣寫CSX,沒有GL 10:28 PARAM需要:

// betterscript.csx: 
public class ScriptWork : IHaveWork 
{ 
    Work(HeavyType obj) 
    { 
     obj.DoSomeWork(); 
    } 
} 
return new ScriptWork(); 

你需要這個接口在你的應用程序:

public interface IHaveWork 
{ 
    void Work(HeavyType obj); 
} 

和腳本應該與您的應用程序引用運行。 您將從腳本中收到IHaveWork的一個實例,然後您應該在您的應用程序中調用Work。

+0

這可能肯定是一些解決方案,但我需要直接設置/訪問我的不同全局類中的許多屬性。 – Chrille

+0

如果您要參考他們的命名空間,您應該可以從腳本訪問其所有公共屬性。 – idanp