我在使用FindPartialView()时遇到了一些奇怪的性能问题,要进行调试我有以下代码,我在发布模式下运行:
var startTime = DateTime.Now;
var view = this.BaseViewEngine.FindPartialView(context, proposedViewPath, useCache);
var timeTaken = DateTime.Now - startTime;
this.log.Write(string.Format("FindPartialView Result: useCache='{0}' proposedViewPath='{1}' TimeTakenMS={2}ms", useCache, proposedViewPath, timeTaken.TotalMilliseconds));
其中BaseViewEngine是在Application_Start中创建的WebFormViewEngine实例。
当不在缓存中时,它会生成
之类的日志FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/TopNavigation.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='False' proposedViewPath='~/Controls/Navigation/TopNavigation.ascx' TimeTakenMs=1607ms
FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/FooterMenu.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='False' proposedViewPath='~/Controls/Navigation/FooterMenu.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/FooterMenuItem.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='False' proposedViewPath='~/Controls/Navigation/FooterMenuItem.ascx' TimeTakenMs=1279ms
当它是:
FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/TopNavigation.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/FooterMenu.ascx' TimeTakenMs=0ms
FindPartialView Result: useCache='True' proposedViewPath='~/Controls/Navigation/FooterMenuItem.ascx' TimeTakenMs=0ms
哪个不会那么糟糕,但我们遇到的问题是它似乎随机地经常从缓存中删除项目(77个日志条目中的17个只相隔几分钟)。因为它无法在缓存中找到它,所以它使用useCache = false运行,这通常需要花费大量时间(我们记录的时间超过4秒)。
首先,是否有人知道为什么需要这么长时间?它没有在调试模式下编译,我们给它一个绝对路径,所以它不应该搜索它。我尝试给它完整的文件系统路径(例如C:\ Web \ Controls \ Navigation \ FooterItem.ascx),但它根本无法工作。
其次有没有办法让它使用自定义视图缓存,所以至少我们可以确保项目保持缓存?
谢谢!
编辑:好到目前为止我已经得到了这个并且它似乎适用于我们的使用模式,是否有人会想到不这样做的充分理由?
/// <summary>
/// Optimised WebFormViewEngine to fix performance issue with FindView / FindPartialView
/// </summary>
public class FastWebFormViewEngine : WebFormViewEngine
{
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
// If absolute path then no need to search for the view
return partialViewName.StartsWith("~")
? new ViewEngineResult(this.CreatePartialView(controllerContext, partialViewName), this)
: base.FindPartialView(controllerContext, partialViewName, useCache);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
// If absolute path then no need to search for the view
return viewName.StartsWith("~") && (string.IsNullOrEmpty(masterName) || masterName.StartsWith("~"))
? new ViewEngineResult(this.CreateView(controllerContext, viewName, masterName), this)
: base.FindView(controllerContext, viewName, masterName, useCache);
}
}