Если это окажется полезным для всех, я с радостью превращу его в вики-сообщество сообщества.
У меня есть несколько медленных страниц в приложении MVC3, и, поскольку в моем коде было мало времени выполнения, я хотел посмотреть, могу ли я узнать больше о том, что заняло так много времени. Не то, чтобы я преуспел, но я получил немного больше мудрости на этом пути.
Здесь ничего нет, что не очевидно никому с опытом MVC. В принципе, я создал свой собственный ActionFilterAttribute, который выглядит так:
public class ProfilerAttribute : ActionFilterAttribute
{
IDisposable actionStep = null;
IDisposable resultStep = null;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
actionStep = MiniProfiler.Current.Step("OnActionExecuting " + ResultDescriptor(filterContext));
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (actionStep != null)
{
actionStep.Dispose();
actionStep = null;
}
base.OnActionExecuted(filterContext);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
resultStep = MiniProfiler.Current.Step("OnResultExecuting " + ResultDescriptor(filterContext));
base.OnResultExecuting(filterContext);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (resultStep != null)
{
resultStep.Dispose();
resultStep = null;
}
base.OnResultExecuted(filterContext);
}
private string ResultDescriptor(ActionExecutingContext filterContext)
{
return filterContext.ActionDescriptor.ControllerDescriptor.ControllerName + "." + filterContext.ActionDescriptor.ActionName;
}
private string ResultDescriptor(ResultExecutingContext filterContext)
{
var values = filterContext.RouteData.Values;
return String.Format("{0}.{1}", values["controller"], values["action"]);
}
Кажется, что это работает хорошо, и в моем случае я узнал, что большую часть времени фактически тратится на часть выполнения ResultExecuting, а не внутри моих действий.
Однако у меня есть некоторые вопросы об этом подходе.
1) Является ли это безопасным для пользователя способом? Я предполагаю, что нет, так как actionfilter создается только один раз, в методе RegisterGlobalFilters() в Global.asax.cs. Если сразу появятся два запроса, actionStep и resultStep будут бесполезны. Это правда? Если да, может ли кто-то, кто знает больше, чем я, способствовал бы умному способу справиться с этим? Работает для меня во время локального профилирования машины, но, вероятно, не так много развертывается на сервере с несколькими людьми, делающими запросы одновременно.
2) Есть ли способ получить более полное представление о процессе выполнения результата? Или я должен просто согласиться с тем, что визуализация представления и т.д. Требует времени? В моем собственном приложении я гарантирую, что весь доступ к базе данных закончен до того, как мой метод действия закончен (с использованием NHibernate Profiler в моем случае), и я хотел бы, чтобы мои представления были тонкими и простыми; Однако любое понимание того, что замедляет рендеринг, все равно может быть полезным. Думаю, использование Mini Profiler в моих объектах модели появилось бы здесь, если бы был выполнен какой-то медленный код с моей стороны.
3) Методы ResultDescriptor, вероятно, являются злыми и ядовитыми. Они работали на меня в моих тестах, но, вероятно, их нужно было заменить чем-то более надежным. Я просто пошел с первыми версиями, которые дали мне что-то наполовину полезное.
Любые другие комментарии к этому также будут очень желанными, даже если они "Это плохая идея, иди умереть в одиночку".