CompilerParameters.GenerateInMemory = false performance issue
I am using RazorEngine to parse html templates in an app, and was writing some NUnit tests to profile the performance areas and investigate potential problems. It seems that when specifying GenerateInMemory = false
, my code is suffering a huge performance hit.
When running each test in NUnit, the total ticks spent in the CompileAssemblyFromDom() method is as follows:
GenerateInMemory = false: 354,493,052 ticks
GenerateInMemory = true: 6,669,711,153 ticks
This is much more extreme impact than I expect for the added cost of some disk IO. Additionally, it seems this time is not linear with the size of the test. For example, when I ran the test for 200 iterations instead of 1000 (in memory = false), the result was 118M ticks, which normalized to the 1000 test iterations is 591M ticks. This is slightly greater than the corresponding test loading into memory, but still an order of magnitude less than the actual performance when the full size test finally completed (I thought it was hanging, but finished while writing this question).
Is there any reason for this huge impact on performance when saving a large number of dynamic assemblies?
Test code:
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 */
And the GetHtmlFromTemplate() code:
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());
}
A bunch of irrelevant code happens here, and eventually we get to the problem area, which is where a CodeDomProvider is used to compile the code:
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: Performance of the CompileAssemblyFromDom()
method when saving a small number of assemblies (<200) to disk is worse than loading to memory, but when the number is increased (~500-1000), the performance is orders of magnitude worse? What causes this strange behavior?
I've found this link in wich the author Rick Strahl says that CodeDomProvider compiler loads compiled assemblies in the Application domain:
Application domains load assemblies, but they cannot unload them!
This is what MSDN says too: see this.
so the problem is that the assemblies are all resident in memory slowing the system.
链接地址: http://www.djcxy.com/p/65098.html