【问题标题】:Ajax calls are slower to controller in physically different file在物理上不同的文件中,Ajax 调用对控制器的速度较慢
【发布时间】:2017-04-19 23:27:26
【问题描述】:

在尝试加速我们的一个 MVC 页面中的一些 ajax 调用时,我遇到了一些我无法真正解释的奇怪行为。我每隔 N 秒就会进行一些 ajax 调用来轮询一些统计信息。

似乎对物理上不同文件中的控制器进行的 ajax 调用比对与视图来源相同的物理文件中的控制器进行的类似调用要慢得多。

查看我的简化示例:

情况1:只有1个文件

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();
        }
    }
}

情况 2:同一文件夹中有 2 个单独的文件

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 });
            }
        }
    }
}

在这两种情况下,ajax 调用都是由 jQuery 进行的,如下所示:

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);
        }
    }
});

现在,两种情况下 ajax 请求的响应时间如下,左侧显示情况 1,右侧显示情况 2:

因此,您可以看到在情况 1 中调用 GetStats()GetAgents() 的平均时间分别为 52.8 ms53.8 ms

但是,在情况 2 中,调用的平均时间为 486.8 ms529.9 ms

我现在的问题是:当这些操作驻留在物理上不同的文件中的控制器中时,对动作进行的 ajax 调用平均比当这些动作驻留在共享相同文件的控制器中时平均慢 10 倍。物理文件作为首先渲染视图的文件?

是不是因为包含渲染视图的动作的文件已经加载并保存在内存中,而单独的文件,如情况 2,每次调用动作时都会打开和关闭?还是发生了更险恶的事情?

【问题讨论】:

  • 我怀疑可能需要OTHER STUFF 才能完全回答这个问题 - 或者进一步缩小范围,直到您可以发布一个显示此行为的完整示例。
  • @AntP 够公平的。我添加了OTHER STUFF,虽然我认为这不会产生影响,因为两种情况下的操作完全相同(调用第三方 URL 以获取一些统计信息/代理)。
  • 在不同文件中具有相关类的控制器被编译到一个 DLL 中,所以进程并不真正知道这两种方式的区别......听起来像是在发生其他事情?
  • @BrianMains 这是有道理的。我将不得不进一步研究发生了什么。当我知道更多时,我会回来报告!

标签: c# ajax asp.net-mvc


【解决方案1】:

您分享了大部分代码,但没有分享_BaseController.cs

  1. 对于每个请求,MVC 使用依赖注入获取控制器。
    [推测] MVC 可能会存储最近使用的控制器,多次返回相同的控制器。但是,如果您要切换控制器,则可能每次都会创建一个新控制器。

  2. 也许_BaseController 默认构造函数中有一些非常慢的代码——也许是数据库查询。这听起来不太可能,但根据我的经验已经发生了。

综合起来,这些因素会导致您描述的减速。

【讨论】:

  • 感谢您的回复。到目前为止,我还没有时间真正进一步调查这个问题,但我仍然打算这样做。您提出的第 1 点可能是有道理的,但很难证明。我认为第 2 点并不是真正的问题,因为这两种情况都使用相同的 _BaseController。但是,我可以尝试进行不依赖于任何 _BaseController 的设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多