【问题标题】:Web Workers handling AJAX calls - optimisation overkill?处理 AJAX 调用的 Web Worker - 优化过度?
【发布时间】:2013-09-17 02:05:13
【问题描述】:

我正在处理使用 Web Worker(如果可用)处理所有 AJAX 请求的代码。这些工作人员几乎只做XMLHttpRequest 对象处理(没有额外的计算)。工作人员创建的所有请求都是异步的 (request.open("get",url,true))。

最近,我遇到了一些关于这段代码的问题,我开始怀疑我是应该花时间修复这个问题还是直接放弃整个解决方案。

到目前为止,我的研究表明,这段代码实际上可能会损害性能。但是,我找不到任何可靠的来源支持这一点。我仅有的两个发现是:

  • 2 岁的 jQuery feature suggestion 使用 Web Worker 进行 AJAX 调用
  • this SO 问题似乎询问了一些不同的东西(在网络工作者与 AJAX 调用中使用同步请求)

谁能给我指出一个讨论这个问题的可靠来源?或者,有没有什么基准可以打消我的疑虑?

[EDIT] 当 WebWorker 也负责解析结果时(JSON.parse),这个问题变得更有趣了。异步解析是否提高了性能?

【问题讨论】:

  • uffffffffffff 我只是在等待一个好的答案。
  • 你可以在这里建立你自己的测试:jsperf.com/webworker-vs-single-thread/11
  • 网络工作者在进行计算量大的工作时会很有帮助。 AJAX 请求主要受 IO 限制。如果除了将结果传递回主应用程序之外,您没有对结果进行任何操作,那么您不太可能看到任何性能优势,并且很可能您的性能会略有下降,因为传递结果会产生一些开销返回。
  • 如果他们给你带来了问题并且他们没有解决任何问题...... :)
  • AJAX 调用本质上是异步的,因此除了调用 JavaScript 引擎之外,它们不会占用太多计算时间。如果您在 Web Worker 代码中解析结果,但如果您在主线程中处理请求的结果,那么 WebWorkers 非常棒,这将是 99% 的计算时间。这意味着它将优化这 1%,这可能没有多大帮助。

标签: javascript ajax asynchronous web-worker


【解决方案1】:

我创建了一个proper benchmark for that on jsperf。根据浏览器的不同,WebWorker 方法比原始 ajax 调用慢 85-95%


注意事项:

  • 由于每个请求的网络响应时间可能不同,我只测试new XMLHttpRequest()JSON.parse(jsonString);。没有进行真正的 AJAX 调用。
  • WebWorker 设置和拆卸操作被测量
  • 请注意,我正在测试单个请求,Webworker 方法的结果对于多个同时请求可能会更好
  • Calvin Metcalf 向我解释说,比较 jsperf 上的同步和异步不会给出准确的结果,他创建了 another benchmark 来消除异步开销。结果仍然表明,WebWorker 方法的速度要慢得多。
  • Reddit discussion了解到,主页面和WebWorker之间传递的数据是复制的,在这个过程中必须进行序列化。因此,仅使用 WebWorker 进行解析没有多大意义,无论如何都必须对数据进行序列化和反序列化,然后才能在主页上使用它们。

【讨论】:

  • +1 - 优化的第一条规则是不要。第二条规则是真的,不要。第三条规则是,如果您必须优化,请确保您对其进行基准测试!
  • @Konrad,用transfering 进行基准测试而不是复制——序列化肯定会失败,这对工人案例来说甚至不公平。
  • @Pacerier 对,现在我们有能力在不序列化的情况下传输数据,这个测试值得重做。随意试一试,让我知道结果,我会更新答案。
  • 花费时间很重要。例如,用户可能会点击触发 AJAX 调用的动画切换开关,我发现主线程中的 JS 活动会导致 CSS 转换中的帧丢失。在移动设备上,设置 XmlHttpRequest 可能需要大约 1 毫秒;我确信向网络工作者发布消息将花费更少的时间。我不太担心将数据传回,这将在任意时间发生,而这在动画期间很容易发生。
【解决方案2】:

首先要记住的是,网络工作者很少会因为花费更少的时间而让事情变得更快,他们让事情变得更快是因为他们将计算负载转移到后台线程,这样与用户交互相关的处理就不会被阻塞。例如,当您考虑传输数据时,进行大规模计算可能需要 8 秒而不是 4 秒。但如果在主线程上完成,整个页面将被冻结 4 秒,这可能是不可接受的。

考虑到这一点,仅将 ajax 调用移出主线程不会为您带来任何好处,因为 ajax 调用是非阻塞的。但是如果你必须解析 JSON 甚至更好,从一个大请求中提取一个小子集,那么 web worker 可以帮助你。

我听说但未确认的一个警告是,工作人员使用与主页不同的缓存,因此如果在主线程和工作人员中加载相同的资源,可能会导致大量重复工作。

【讨论】:

【解决方案3】:

你在错误的地方优化你的代码。

AJAX 请求已经在单独的线程中运行,并在完成后返回主事件循环(并调用定义的回调函数)。

Web Worker 是线程的接口,用于计算昂贵的操作。就像在经典桌面应用程序中,当您不想通过需要很长时间的计算来阻塞接口时。

【讨论】:

    【解决方案4】:

    异步IO是Javascript的一个重要概念。

    首先,您的请求已经是异步的,IO 是非阻塞的,在您的请求期间,您可以运行任何其他 Javascript 代码。在 worker 中执行回调比请求更有趣。

    其次,Javascript引擎执行所有代码在同一个线程中,如果创建新线程,则需要处理与worker message api的数据通信(见Semaphore)。

    总之,JavaScript 的异步和单线程特性非常强大,请尽可能多地使用它,并且仅在您真正需要时才创建工作线程,例如在较长的 Javascript 进程中。

    【讨论】:

    • 在 webworker 中执行请求似乎从一开始就显得有点矫枉过正。真正的问题是在 webworker 中执行请求 JSON.parse 是否有意义。我的基准测试表明它没有,至少对于平均大小的 JSON 字符串。
    • web worker 的相关部分是 JSON.parse,它应该专门用于大型 json 内容。
    • 我得到的响应是 xml。如何将 jquery 收到的文档对象传递给工作人员?它不是可转移的对象
    【解决方案5】:

    根据我的经验,Web Workers不应该用于 AJAX 调用。首先,它们是异步的,这意味着在您等待信息返回时代码仍会运行。

    现在,使用 Worker 来处理响应绝对是您可以使用 Web Worker 的事情。一些例子:

    • 解析响应以构建大型模型
    • 从响应中计算大量数据
    • 将 Shared Web Worker 与模板引擎结合使用并结合 AJAX 响应来构建 HTML,然后将其返回以附加到 DOM。

    编辑:另一个不错的读物是:Opinion about synchronous requests in web workers

    【讨论】:

    • 我想解析响应。但是当我将数据发送到 worker 中解析时,我收到一个错误,因为数据类型是 xml 并且它不是可传输的对象。所以我必须在主线程中解析数据才能发布到消息中,并且会被克隆。
    • 处理 AJAX 调用仍然是同步的,所以在工作线程中执行它们仍然是有益的。当然,要在 worker 中处理它们,您首先必须在 worker 上执行 XHR
    猜你喜欢
    • 2011-06-17
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2019-09-07
    • 2012-05-24
    相关资源
    最近更新 更多