2016-12-05 18 views
6

Podczas próby przyspieszenia niektórych wywołań ajaxowych na jednej z naszych stron MVC, natknąłem się na dziwne zachowanie, którego tak naprawdę nie potrafię wyjaśnić. Mam kilka wywołań ajaxowych co N sekund do odpytywania niektórych statystyk.Połączenia Ajax są wolniejsze w stosunku do kontrolera w fizycznie różnym pliku

Wygląda na to, że wywołania ajax do kontrolera w fizycznie innym pliku są znacznie wolniejsze niż podobne wywołania do kontrolera w tym samym pliku fizycznym, z którego pochodzi widok.

Zobacz moje uproszczone przykłady:

Sytuacja 1: Tylko 1 plik

FooController.cs

namespace FooBar.Areas.FooArea.Controllers 
{ 
    [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] 
    public class FooTestController: _BaseController 
    { 
     public JsonResult GetStats() 
     { 
      try 
      { 
       var req = new RestRequest() { Method = Method.GET }; 
       req.AddHeader("Content-Type", "application/json"); 
       req.AddHeader("Accept", "application/json"); 
       req.AddParameter("apikey", /*APIKEY*/); 

       var client = new RestClient(/*STATSURL*/); 
       var response = client.Execute(req); 

       if (response.StatusCode == HttpStatusCode.OK) 
        return Json(new { success = true, content = response.Content }); 
       else 
        return Json(new { success = false }); 
      } 
      catch 
      { 
       return Json(new { success = false }); 
      } 
     } 

     public JsonResult GetAgents() 
     { 
      var req = new RestRequest() { Method = Method.GET }; 
      req.AddHeader("Content-Type", "application/json"); 
      req.AddHeader("Accept", "application/json"); 
      req.AddParameter("apikey", /*APIKEY*/); 

      try 
      { 
       var client = new RestClient(/*AGENTSURL*/); 
       var response = client.Execute(req); 

       if (response.StatusCode == HttpStatusCode.OK) 
        return Json(new { success = true, content = response.Content }); 
       else 
        return Json(new { success = false }); 
      } 
      catch 
      { 
       return Json(new { success = false }); 
      } 
     } 
    } 

    public class FooController : _BaseController 
    { 
     // VIEW OF THE PAGE MAKING THE AJAX REQUESTS 
     public ActionResult Index() 
     { 
      Title = "Home"; 
      return View(); 
     } 
    } 
} 

Sytuacja 2: 2 oddzielne pliki w tym samym folderze

FooController.cs

namespace FooBar.Areas.FooArea.Controllers 
{ 
    public class FooController: _BaseController 
    { 
     // VIEW OF THE PAGE MAKING THE AJAX REQUESTS 
     public ActionResult Index() 
     { 
      Title = "Home"; 
      return View(); 
     } 
    } 
} 

FooAjaxController.cs

namespace FooBar.Areas.FooArea.Controllers 
{ 
    [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] 
    public class FooAjaxController: _BaseController 
    { 
     public JsonResult GetStats() 
     { 
      try 
      { 
       var req = new RestRequest() { Method = Method.GET }; 
       req.AddHeader("Content-Type", "application/json"); 
       req.AddHeader("Accept", "application/json"); 
       req.AddParameter("apikey", /*APIKEY*/); 

       var client = new RestClient(/*STATSURL*/); 
       var response = client.Execute(req); 

       if (response.StatusCode == HttpStatusCode.OK) 
        return Json(new { success = true, content = response.Content }); 
       else 
        return Json(new { success = false }); 
      } 
      catch 
      { 
       return Json(new { success = false }); 
      } 
     } 

     public JsonResult GetAgents() 
     { 
      var req = new RestRequest() { Method = Method.GET }; 
      req.AddHeader("Content-Type", "application/json"); 
      req.AddHeader("Accept", "application/json"); 
      req.AddParameter("apikey", /*APIKEY*/); 

      try 
      { 
       var client = new RestClient(/*AGENTSURL*/); 
       var response = client.Execute(req); 

       if (response.StatusCode == HttpStatusCode.OK) 
        return Json(new { success = true, content = response.Content }); 
       else 
        return Json(new { success = false }); 
      } 
      catch 
      { 
       return Json(new { success = false }); 
      } 
     } 
    } 
} 

W obu sytuacjach, połączenia są wykonane z Ajax jQuery następująco:

jQuery

$.ajax({ 
    url: // URL TO ACTION DEPENDING ON SITUATION, 
    type: "POST", 
    dataType: "json", 
    cache: false, 
    success: function (result) 
    { 
     if (result.success) 
     { 
      var content = JSON.parse(result.content); 
      console.log(content); 
     } 
    } 
}); 

Teraz czasy odpowiedzi z ajax wniosków dotyczących obu sytuacjach są następujące, ze sytuacja 1 wyświetlana po lewej i sytuacji 2 na prawej:

enter image description here enter image description here

Tak, jak można średni czas połączenia wykonanego na GetStats() i GetAgents() w sytuacji 1 to odpowiednio: 52,8 ms i 53,8 ms.

Jednak w sytuacji 2, średni czas połączeń jest 486,8 ms i 529,9 ms.

Moje pytanie brzmi: jak to możliwe, że wywołania ajax wywoływane w działaniach są średnio 10 razy wolniejsze, gdy te akcje znajdują się w kontrolerze w fizycznie odmiennym pliku, niż gdy te akcje znajdują się w kontrolerze, który dzieli ten sam plik fizyczny co plik renderujący widok?

Czy to dlatego, że plik zawierający akcję renderowania widoku jest już załadowany i przechowywany w pamięci, podczas gdy oddzielny plik, jak w sytuacji 2, jest otwierany i zamykany za każdym razem, gdy wywoływana jest akcja? Czy może dzieje się coś bardziej złowrogiego?

+2

Podejrzewam, że "OTHER STUFF" może być potrzebne, aby w pełni odpowiedzieć na to pytanie - albo je zawęzić, dopóki nie będzie można opublikować pełnego przykładu pokazującego to zachowanie. –

+0

@AntP Wystarczająco fair. Dodałem "OTHER STUFF", chociaż nie sądziłem, że to by miało znaczenie, ponieważ działania w obu sytuacjach robią dokładnie to samo (wywołanie adresu URL strony trzeciej w celu uzyskania statystyk/agentów). – ZiNNED

+1

Kontrolery z powiązanymi klasami w różnych plikach są kompilowane do biblioteki DLL, więc proces tak naprawdę nie zna różnicy w żaden sposób ... brzmi jak dzieje się coś innego? –

Odpowiedz

0

Udostępniłaś większość kodu ale nie _BaseController.cs

  1. na każde żądanie, MVC dostaje kontrolera przy użyciu iniekcji zależność.
    [spekulacja] MVC może przechowywać ostatnio używany kontroler, zwracając ten sam kilka razy. Jednak jeśli przełączasz kontrolery, być może za każdym razem tworzy on nowy.

  2. Być może istnieje pewien bardzo powolny kod w domyślnym konstruktorze _BaseController - być może zapytania do bazy danych. Brzmi to mało prawdopodobne, ale zdarzyło się w moim doświadczeniu.

Łącznie te rzeczy spowodują spowolnienie, które opisujesz.

+0

Dzięki za odpowiedź. Do tej pory nie miałem czasu, aby to dokładniej zbadać, ale nadal zamierzam to zrobić. Twój punkt 1 może mieć sens, ale trudno go udowodnić. Punkt 2 tak naprawdę nie jest problemem, ponieważ obie sytuacje wykorzystują ten sam _BaseController. Mógłbym jednak spróbować dokonać konfiguracji, która nie zależy od żadnego kontrolera _BaseController. – ZiNNED