C#MVC FindView / FindPartialView奇怪的性能问题

时间:2013-03-27 15:31:35

标签: c# performance model-view-controller

我在使用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);
    }
}

0 个答案:

没有答案