2

私はRazorEngineを使用してアプリ内の html テンプレートを解析しており、パフォーマンス領域をプロファイリングして潜在的な問題を調査するためにいくつかの NUnit テストを作成していました。を指定するGenerateInMemory = falseと、コードのパフォーマンスが大幅に低下するようです。

NUnit で各テストを実行する場合、CompileAssemblyFromDom() メソッドで費やされるティックの合計は次のとおりです。

GenerateInMemory = false:      354,493,052 ticks
GenerateInMemory = true:     6,669,711,153 ticks

これは、一部のディスク IO の追加コストに対して予想されるよりもはるかに極端な影響です。さらに、今回はテストのサイズに比例していないようです。たとえば、1000 回ではなく 200 回の反復でテストを実行した場合 (メモリ内 = false)、結果は 118M ティックで、1000 回のテスト反復に正規化すると 591M ティックになります。これは、対応するテストのメモリへのロードよりもわずかに大きいですが、フル サイズのテストが最終的に完了したときの実際のパフォーマンスよりも 1 桁小さくなっています (ハングしていると思いましたが、この質問を書いている間に終了しました)。

多数の動的アセンブリを保存するときにパフォーマンスに大きな影響を与える理由はありますか?

テストコード:

        for (int i = 0; i < 1000; i++)
        {
            string s = "<div>" + i + " some random text blah blah... no code specified</div>";
            parser.GetHtmlFromTemplate(s, i.ToString());

        }

        /*
         * Result:
         *     _codeDomProvider.CompileAssemblyFromDom:       354493052 ticks
         */
        /* ... collect timing stats */

GetHtmlFromTemplate() コード:

    public string GetHtmlFromTemplate(string template, string templateCacheName)
    {
        if (template == string.Empty) return string.Empty;

        ITemplate templateInstance = templateService.GetTemplate(template, null, templateCacheName);
        return templateInstance.Run(new ExecuteContext());
    }

ここで大量の無関係なコードが発生し、最終的にコードをコンパイルするために CodeDomProvider が使用される問題領域に到達します。

            var compileTimer = new Stopwatch();
            compileTimer.Start();
            var compileUnit = GetCodeCompileUnit(context.ClassName, context.TemplateContent, context.Namespaces,
                                                 context.TemplateType, context.ModelType);
            compileTimer.Stop();



            var @params = new CompilerParameters
            {
                GenerateInMemory = InMemory, //in memory is a property of this object, and is set accordingly for each test
                GenerateExecutable = false,
                IncludeDebugInformation = false,
                CompilerOptions = "/target:library /optimize"
            };

            //{...} do some reflection to get the referenced assemblies


            var compileFromDomTimer = new Stopwatch();
            compileFromDomTimer.Start();

            var tuple = Tuple.Create(_codeDomProvider.CompileAssemblyFromDom(@params, compileUnit), someString);
            compileFromDomTimer.Stop();

TLDR:少数のアセンブリ (<200) をディスクに保存するときのメソッドのパフォーマンスは、CompileAssemblyFromDom()メモリにロードするよりも悪いですが、数が増えると (~500-1000)、パフォーマンスは桁違いに悪くなりますか? この奇妙な動作の原因は何ですか?

4

1 に答える 1

0

著者の Rick Strahl が、CodeDomProvider コンパイラがコンパイル済みアセンブリをアプリケーション ドメインにロードすると述べているこのリンクを見つけました。

アプリケーション ドメインはアセンブリをロードしますが、アンロードできません!

これはMSDNも言っていることです:これを見てください。

問題は、アセンブリがすべてメモリに常駐しており、システムの速度が低下していることです。

于 2015-07-01T11:01:15.083 に答える