Roslyn(CSharpScript).Net腳本編譯引擎使用過程記憶體增漲與穩定的方式

目       錄

1.      引用程式集... 1

2.      記憶體增漲的情況... 2

3.      記憶體穩定的情況... 4

1.   引用程式集

     Roslyn 是微軟公司開源的 .NET 編譯器。編譯器支援 C# 和 Visual Basic 程式碼編譯,並提供豐富的程式碼分析 API。使用非常方便,增加引用腳本編譯引擎程式集:Microsoft.CodeAnalysis.CSharp.Scripting.dll,如下圖:

 

    但是在使用過程中會出現記憶體增漲的情況,如果要解決這個問題,需要對程式碼進行結構化處理。下面演示記憶體增漲和穩定兩種情況。

2.   記憶體增漲的情況

  直接使用內部的API介面:CSharpScript.EvaluateAsync,完整程式碼如下:

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

namespace ConsoleApp1
{
     public class Program
    {
        private static ScriptOptions scriptOptions=ScriptOptions.Default.WithEmitDebugInformation(false);
        private static string script="int num=1+2;Write(num);return num;";
        private static Custom custom = new Custom();
        static void Main(string[] args)
        {
            while(true)
            {
                MemoryRise();

                Thread.Sleep(10);
            }
        }

        //記憶體內漲
        public static void MemoryRise()
        {
            object result = CSharpScript.EvaluateAsync(script,scriptOptions,custom,typeof(Custom)).Result;

            if(result!=null)
            {
                Console.WriteLine(DateTime.Now.ToString ()+" Result:"+result.ToString ());

            }
        }
    }

    public class Custom
    {
        public void Write(int num)
        {
            Console.WriteLine("Custome.Write:"+num.ToString());
        }
    }
}

   在調試程式碼的過程,每次執行程式碼會把程式碼生成一個新的程式集模組,並且在新的程式域中載入,沒有找到卸載程式域和模組的方法。如下圖:

   正式運行編譯好的程式集,記憶體明顯增漲的比較快。如下圖:

3.   記憶體穩定的情況

  要避免對相同程式碼進行反覆編譯和載入模組,需要對程式碼進行特殊處理。程式碼如下:

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

namespace ConsoleApp1
{
     public class Program
    {
        private static ScriptOptions scriptOptions=ScriptOptions.Default.WithEmitDebugInformation(false);
        private static Script baseScript = CSharpScript.Create("", options: scriptOptions, globalsType: typeof(Custom));
        private static Dictionary<string, Script<object>> loadScriptCache = new Dictionary<string, Script<object>> ();
        private static string script="int num=1+2;Write(num);return num;";
        private static Custom custom = new Custom();

        static void Main(string[] args)
        {
            while(true)
            {
                MemoryNormal();

                Thread.Sleep(10);
            }
        }

        //記憶體穩定
        public static void MemoryNormal()
        {
            if (!loadScriptCache.ContainsKey(script))
                loadScriptCache.Add(script, baseScript.ContinueWith<object>(script));

            ScriptState<object> scriptState = loadScriptCache[script].RunAsync(custom).Result;
             
            if(scriptState.ReturnValue!=null)
            {
                Console.WriteLine(DateTime.Now.ToString ()+" Result:"+scriptState.ReturnValue.ToString ());
            }
        }
    }

    public class Custom
    {
        public void Write(int num)
        {
            Console.WriteLine("Custome.Write:"+num.ToString());
        }
    }
}

   只會編譯和載入一次相同程式碼的程式集模組,編譯調試過程如下圖:

   正式運行編譯好的程式集,運行一段時間,記憶體穩定在80多MB。如下圖:


物聯網&大數據技術 QQ群:54256083
物聯網&大數據項目 QQ群:727664080
網站://www.ineuos.net
QQ:504547114
微信:wxzz0151
部落格://www.cnblogs.com/lsjwq
微信公眾號:iNeuOS
 

 

Tags: