2013-08-02 5 views
1

Я создал приложение, которое отображает mvc-представления в строки и использует HiQPDF для рендеринга PDF-отчета. Это хорошо работает, однако, повторные звонки в IView.Render вызывает значительное ухудшение производительности. Каждый вызов занимает около 1 с дольше, чем предыдущий вызов, - и отображаемый html почти то же самое.Rendering View to string performance

Кто-нибудь знает о других способах рендеринга html, которые не принимают такого рода производительность? Кто-нибудь знает, почему я вижу такую ​​плохую производительность с помощью этого кода?

protected string RenderViewToStringInternal(string viewPath, object model, 
                bool partial = false, 
                string master = null) 
     { 
      //Find cached view 
      ViewEngineResult viewEngineResult = _cachedViews.ContainsKey(viewPath) ? _cachedViews[viewPath] : null; 

      if (viewEngineResult == null) 
      { 
       //Get view engine result 
       if (partial) 
        viewEngineResult = ViewEngines.Engines.FindPartialView(Context, viewPath); 
       else 
        viewEngineResult = ViewEngines.Engines.FindView(Context, viewPath, master); 

       if (viewEngineResult != null) 
       { 
        _cachedViews.Add(viewPath, viewEngineResult); 
       } 
      } 

      if (viewEngineResult == null) 
       throw new FileNotFoundException("View not found"); 

      // get the view and attach the model to view data 
      var view = viewEngineResult.View; 

      Context.Controller.ViewData.Model = model; 

      string result = null; 

      using (var sw = new StringWriter()) 
      { 
       var ctx = new ViewContext(Context, view, 
              Context.Controller.ViewData, 
              Context.Controller.TempData, 
              sw); 

       DateTime start = DateTime.Now; 
       **view.Render(ctx, sw);** //This line's performance degrades after subsequent calls with similar data 
       DateTime end = DateTime.Now; 

       Logging.LogInformation(Logging.TraceType.UI, string.Format("ViewRenderer.RenderViewToStringInternal view.Render execution time: {0}", end.Subtract(start).TotalSeconds)); 

       viewEngineResult.ViewEngine.ReleaseView(Context, view); 

       result = sw.ToString(); 
      } 

      return result; 
     } 
+0

может быть своего рода блокировкой, является ли представление, выполняющее все, что ему нужно, и выполнять вычисления или доступ к файлам? Попробуйте визуализировать представление с контроллера и многократно возвратить html и посмотреть, есть ли у него также медленный –

+0

, который я тестировал через контроллер (через рендеринг всех страниц отчета через частичные). Выполнение этого снова и снова (обновление страницы в браузере) показывает очень хорошую производительность. Каждая загрузка страницы остается постоянной .5 секунд. Если после 10 или 20 рендерингов с использованием приведенного выше кода может потребоваться более 60 секунд для небольшой части отчета ... – voidsstr

+0

Я должен добавить - это не происходит на моем ноутбуке разработки с теми же данными образца. Это происходит только на наших серверах разработки и промежуточного уровня (Im, предполагая, что это произойдет и в производстве). – voidsstr

ответ

0

Как описано в моих комментариях на мой собственный вопрос - это вопрос только произошло в виртуальную среду. Я никогда не определял, почему этот код работал медленно, однако для решения моей проблемы с производительностью я изменил свой код, чтобы получить каждую из страниц PDF через отдельные веб-запросы, которые отображали отдельные частичные части MVC. Это резко увеличило пропускную способность, а полученные запросы заняли менее 100 мс.

0

Я использую следующие, чтобы сделать вид на строки и не видел ни одного из вопросов, которые вы описали

public static class ContollerContextExtensions 
    { 
     /// <remarks>If you have any validation summaries they will not be populated by this method</remarks> 
     public static string RenderPartialToString(this ControllerContext ControllerContext, string viewName, object model) 
     { 
      if (string.IsNullOrEmpty(viewName)) 
       viewName = ControllerContext.RouteData.GetRequiredString("action"); 
      ViewDataDictionary ViewData = new ViewDataDictionary(); 
      TempDataDictionary TempData = new TempDataDictionary(); 
      ViewData.Model = model; 

      using (StringWriter sw = new StringWriter()) 
      { 
       ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); 
       ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); 
       viewResult.View.Render(viewContext, sw); 

       return sw.GetStringBuilder().ToString(); 
      } 
     } 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="ControllerContext"></param> 
     /// <param name="viewName"></param> 
     /// <param name="model"></param> 
     /// <returns></returns> 
     /// <remarks>If you have any validation summaries they will not be populated by this method</remarks> 
     public static string RenderViewToString(this ControllerContext ControllerContext, string viewName, object model, string masterName = null) 
     { 
      if (string.IsNullOrEmpty(viewName)) 
       viewName = ControllerContext.RouteData.GetRequiredString("action"); 
      ViewDataDictionary ViewData = new ViewDataDictionary(); 
      TempDataDictionary TempData = new TempDataDictionary(); 
      ViewData.Model = model; 

      using (StringWriter sw = new StringWriter()) 
      { 
       ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, masterName); 
       ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); 
       viewResult.View.Render(viewContext, sw); 

       return sw.GetStringBuilder().ToString(); 
      } 
     } 
    } 
+0

Повторно ли вы вызываете этот метод в одном веб-запросе? В моем сценарии я обрабатываю представления html до 100 раз в одном веб-запросе. Первые вызовы бывают быстрыми, но каждый запрос занимает около 1 с дольше, чем предыдущий. Чтобы сделать вещи более раздражающими, это происходит только на наших виртуальных/промежуточных серверах, которые являются виртуальными. Это не происходит на моем ноутбуке разработки i7 i7. – voidsstr

+0

Итак, 1 веб-запрос от клиента вызывает действие на моем контроллере. Затем это действие вызывает мой рендер для html-метода до 100 раз. Каждый раз занимает примерно секунду больше, чем предыдущий. Последующие веб-запросы от клиента «сбрасывают» проблему с производительностью - представление первой пары для html-рендеринга выполняется быстро, а затем они начинают ухудшаться примерно на 1 с за звонок ... очень странно – voidsstr

+0

Да в течение одного запроса я нахожу это довольно немного в по крайней мере, 100 раз, как вы упоминаете, самое большое замедление, которое я заметил, это сам конвертер HTML в PDF –