我创建了一个用于构建和发送电子邮件的Windows服务。我使用Razor Engine来解析电子邮件模板。我正在使用动态ExpandoObject来创建模型。
我的问题是,当每个电子邮件被创建并发送时,内存正在增加,但它从未被释放。我已经使用Ants Memory分析器(我之前没有使用过这个)来描述该服务,但它显示了以下结果:
使用Razor Engine
使用Razor.Parse(文本,模型)解析200封电子邮件
第1代:12.9kb
第2代: 15.88mb
大对象堆:290.9kb
分配给.NET的未使用内存:3.375mb
不受管理:69.51mb
内存碎片总数:197
没有剃刀引擎
返回200封未经解析的电子邮件。
第1代:13.87kb
第2代:3.798mb
大对象堆:95.58kb
分配给.NET的未使用内存:4.583mb
不受管理:44.58mb
内存碎片总数:7
使用Razor,最大的第2代实例是:
System.Reflection.Emit __FixUpData [] - 2,447,640个实时字节,3,138个实例
有谁知道为什么对象没有被释放而第二代正在增长?有没有办法在每次我想解析模板时都有一个新的RazorEngine实例,当它完成时它将不被引用并将转到GC。
我曾尝试在每次解析模板时创建一个新的Template服务实例,但这并没有产生影响
using (ITemplateService templateService = new TemplateService())
{
result = templateService.Parse<ExpandoObject>(text, model);
}
答案 0 :(得分:2)
每次解析模板时,RazorEngine 都会编译内存中的程序集。
这可能会变得昂贵。
您应该尽可能多地重复使用模板。
答案 1 :(得分:1)
旧问题,但要激活模板缓存,您必须为Parse方法提供“缓存”参数(可以/应该是模板的路径):
return RazorViewService.Parse(File.ReadAllText(path), model, null, cache);
答案 2 :(得分:0)
编译模板时,创建的动态程序集将加载到当前的appdomain中。没有任何工具可以卸载它们,因此当您编译更多模板时,内存会不断增长。
你可以使用RazorEngine 3.x中的IsolatedTemplateService来解决这个问题。它的作用是将编译后的模板加载到新的appdomain中。当该appdomain被垃圾收集时,也会收集加载到该appdomain中的模板程序集。但是有一些限制 - 例如无法使用动态模型(Expando对象)或匿名模型。该模型还需要可序列化。
从RazorEngine的作者那里看出来:http://www.fidelitydesign.net/?p=473
答案 3 :(得分:0)
如果您使用相同的模板,请重复调用RazorEngine.Compile,然后再调用Razor.Run,以确保模板只编译一次。
另外我相信在构建中启用DEBUG时,RazorEngine似乎会泄漏内存。确保您的生产代码是使用Release配置文件构建的,即不使DEBUG编译器保持不变。