2012-09-06 29 views
7

電子メールを作成して送信するためのWindowsサービスを作成しました。私はRazor Engineを使って電子メールのテンプレートを解析しています。私は動的なExpandoObjectを使用してモデルを作成しています。RazorEngineメモリ使用量

私の問題は、各電子メールが作成され、送信されたメモリが増加しているが、決してリリースされていないことです。私はアリメモリープロファイラでサービスをプロファイリングしている(私は前にこれを使用していない)が、それは次のような結果を示している。

レイザーエンジンで

Razor.Parse(テキスト、モデルで200通の電子メールの解析します)

ジェネレーション1:12.9キロバイト

ジェネレーション2:15.88メガバイト

ラージオブジェクトヒープ:.NETに割り当てられた290.9キロバイト

未使用メモリ:3.375メガバイト

非管理

:69.51メガバイト

メモリの断片の総数:197

んレイザーエンジン

200個の電子メールを解析していないテキストを返す。

ジェネレーション1:13.87キロバイト

ジェネレーション2:3.798メガバイト

ラージオブジェクトヒープ:95.58キロバイト

未使用のメモリ.NETに割り当てられた:4.583メガバイト

アンマネージ:44.58 mb

合計メモリフラグメント数:7

かみそりで

最大の世代の2つのインスタンスは以下のとおりです。

System.Reflection.Emit __FixUpData [] - 2447640ライブバイト、3,138インスタンス

は、オブジェクトが解放されていない理由を任意のアイデアを誰を持っており、第2世代は成長していますか?テンプレートを解析するたびにRazorEngineの新しいインスタンスを作成する方法はありますか?終了すると、テンプレートは参照されず、GCに移動します。

アイブ氏は、テンプレートのサービスの新しいインスタンス私はテンプレートを解析するたびに作成しようとしたが、これhasntが違い

using (ITemplateService templateService = new TemplateService()) 
{ 
    result = templateService.Parse<ExpandoObject>(text, model); 
} 
+0

これは古い質問ですが、 'Parse()'を呼び出すとテンプレートがキャッシュされるとは思いません。私がやったことは 'Razor.GetTemplate()'を使い、返された 'ITemplate'インスタンスに対して' Run() 'を呼び出すことでした。アセンブリがどのくらいのメモリを使用しているかを確認するには、適切にキャッシュされている場合は、テンプレートごとに1つのアセンブリのみが必要です。 – mao47

+0

テンプレートを正常にキャッシュしましたか?私のサービスのメモリはまだ増加し、ガベージコレクションは一度も行われません。メモリ使用量が減少したことに気付きましたか? – ministrymason

+0

現在、ITテンプレートを作成しています。template = Razor.Resolve(templateFileName、model); string result = template.Run();しかし、記憶はまだ馬鹿げて成長する。 – ministrymason

答えて

2

テンプレートを解析するたびに作られた、RazorEngine は、メモリ内のアセンブリをコンパイルします。
これは高価になることがあります。

可能な限りテンプレートを再利用する必要があります。

+1

なぜそうではありませんかそれはオブジェクトを解放する?何を参考にしていますか? – ministrymason

+0

おそらくその過剰なのでしょうか?私が欲しいのは、動的モデルで文字列を解析することです。私は、各テンプレートが解析された後に、それが必要ないので、かみそりの中のすべてが解放されると思いましたか? – ministrymason

+0

@ administrymason:動的アセンブリのアンロードは手間がかかります。 – SLaks

0

テンプレートをコンパイルすると、作成されたダイナミックアセンブリが現在のappdomainにロードされます。それらをアンロードする機能はありませんので、より多くのテンプレートをコンパイルすると、メモリは増え続けます。

RazorEngine 3.xでIsolatedTemplateServiceを使用すると、この問題を回避できます。それはコンパイルされたテンプレートを新しいappdomainにロードすることです。そのappdomainがガベージコレクトされると、そのappdomainにロードされたテンプレートアセンブリも同様に収集されます。ただし、動的モデル(Expandoオブジェクト)や匿名モデルを使用できないなど、いくつかの制限があります。モデルもシリアライズ可能である必要があります。 RazorEngineの作者から

チェックこのアウト:http://www.fidelitydesign.net/?p=473

+0

私は動的モデルを使用しているので、IsolatedTemplateServiceは使用できません。記憶が絶えず成長するのを止める方法は他にありませんか?テンプレートをキャッシュした方が良いでしょうか?現時点では、テンプレートを取得し、それをテンプレート名ではなく文字列としてRazorEngineに渡します。 – ministrymason

+0

RazorEngineを使用する最良の方法は何ですか?作成されたアプリケーションのメモリは2GBまで増加しました。私は他の人々が問題を抱えているようには見えないと信じていません。 – ministrymason

1

古い質問が、あなたは/あなたのテンプレートへのパスである必要がありますすることができた(Parseメソッドに「キャッシュ」引数を指定する必要がありますテンプレートキャッシュを有効にするには):

return RazorViewService.Parse(File.ReadAllText(path), model, null, cache); 
0

あなたが同じテンプレートを使用している場合は、繰り返しテンプレートは一度だけコンパイルされることを保証するために、後に続いRazor.Runが一度RazorEngine.Compileを呼び出します。

また、ビルドでDEBUGが有効になっていると、RazorEngineのメモリがリークしているようです。プロダクションコードがReleaseプロファイル、つまりDEBUGコンパイラ定数なしでビルドされていることを確認してください。