【问题标题】:Mysterious severe performance issue on mobile Safari for just one web page移动 Safari 上只有一个网页的神秘严重性能问题
【发布时间】:2014-03-07 14:27:37
【问题描述】:

我有一个非常大(如功能丰富的)响应式网站。它由 150 多个不同的 UI 页面组成,到目前为止,在移动设备上的渲染和性能都很好(我使用 iPhone5 进行测试,偶尔使用其他设备)。

除了一页,我现在正在编码。这是临时开发 URL:

http://www.jungledragon.org/apps/jd3/daylight

在 Mobile Safari 上,此页面的性能极差: - 加载需要几秒钟,比所有其他页面慢得多 - 加载后,触摸滚动可能需要 5-10 秒才能完成任何操作 - 移动 Safari 整体变得无响应或接近它

我正在尝试解决问题的根本原因,但到目前为止还没有成功。我无法在任何使用小视口的桌面浏览器上重现这一点,甚至在桌面 Safari 上也无法重现。在桌面上,我检查了几个 Web 调试器以检查是否有任何长时间运行的进程,但没有发现。

关于页面功能的一些解释:

  1. 它将尝试检测您的当前位置(使用我发现的警报,这需要很少的时间)
  2. 根据您当前的位置和当前日期,它将计算当天的太阳时间。这也几乎是即时的
  3. 根据suntimes动态生成表格,最后显示在屏幕上

这是我在移动 Safari 上看到的详细信息:

  1. 服务器响应很好,页面加载很快,很快就会显示站点标题
  2. 接下来,内容正文为空白,并保持空白几秒钟(我无法解释)
  3. 最后,渲染了 suntimes 表。
  4. 这完成了页面,但到目前为止,页面和浏览器都非常缓慢,滚动需要很长时间,并且 Safari 控件几乎没有响应。它的外观和感觉就像浏览器随时可能崩溃一样。

根据我迄今为止的研究,并鉴于网站上所有其他页面的良好性能,我完全不知道是什么原因造成的。

编辑:我使用 BrowserStack 做了一些测试:

  • iPhone 4S:没问题
  • iPhone 5S:没问题
  • 银河 SII:没问题
  • HTC One X:没问题
  • iPhone 5:与上述相同的问题

所以我在任何桌面浏览器上都没有看到这个问题,在除 iPhone 5 (iOS7) 之外的任何移动设备上都没有。

Edit2:根据收到的 cmets 添加更多发现和解释:

这个问题似乎与动画无关。为此,我有许多证明点。一个简单的证明点是该页面没有进行任何视觉渲染,这与网站上没有性能问题的其他 100 多个页面有很大不同。

可以通过了解此特定页面中发生的情况来解释第二个证明点。会发生什么:

  1. 系统会检测当前用户的时间和位置。现在假设用户实际上允许位置共享。使用一个简单的警报,我已经能够证明位置检测不是瓶颈。

  2. 根据用户的时间和位置,计算日光时段。这是通过使用 Suncalc JS 库 (https://github.com/mourner/suncalc) 完成的。

  3. Suncalc 库返回给定日期和位置的日光时段数组。我将该数组呈现为具有彩色背景行的表格。就是这样。

渲染具有 12 行和不同背景颜色的表格不太可能导致如此大的问题。因此,我的理论在于第 2 步是根本原因。 Suncalc 库中有很多高级数学。我在想(还没有证据)我的移动处理器在这类操作上很糟糕,和/或特定计算由于某种原因导致内存使用达到峰值(甚至是泄漏)。

作为一个额外的证明点:在移动设备上加载页面后,使用日期旁边的向右箭头导航到“明天”。您将再次看到极其糟糕的性能。在这一步中,没有网络活动,没有位置检测,什么都没有,只有计算和一些非常简单的渲染。这验证了我的理论,即问题可能出在计算上。

【问题讨论】:

  • 仅供参考,我将它加载到我的 Galaxy SIII 上的 Chrome 应用程序中,并注意到您描述的相同问题。我想知道它是否与JS引擎有关? Chrome 使用 Blink(WebKit 的一个分支),不确定 Mobile Safari 使用什么。
  • 您在此处制作的动画是否比在其他网页上多?操作(通过动画)多个 DOM 元素通常会削弱移动设备,您甚至不会在任何现代桌面上注意到它(无论分辨率如何)。这将是我要看的第一个地方,并且可能将所有内容都移到 requestAnimationFrame 中。即便如此,您仍需要注意有多少元素通过直接 JS 或级联转换进行动画处理。
  • @CullenJ 感谢您的测试!请参阅我更新的问题以获得一些解释。
  • @MattPileggi 请看我更新的问题,我相信问题可能是计算,而不是动画。
  • 我通过分析器运行该页面,但没有看到任何繁重的计算负载。

标签: iphone responsive-design mobile-safari


【解决方案1】:

遗憾的是,该平台上的原生 Javascript 分析器似乎不存在。您可能还想尝试引用in this answerJavascript Microtime function。您将需要在您认为可能存在瓶颈的位置使用调用播种脚本。

【讨论】:

    【解决方案2】:

    刚刚在我的 S3 上通过 Chrome 远程调试器 (https://developers.google.com/chrome-developer-tools/docs/remote-debugging) 运行了这个,看起来 Modernizr 的 cancelZoom 函数(显示在 jd3_0006.js 中)被递归调用太多次或被太宽的选择器调用。我已将配置文件上传到 Dropbox:https://www.dropbox.com/s/kubxk44smm6qqkx/jungledragon_debug..zip

    您可以在“配置文件”选项卡上将它们导入 Chrome 的调试器。

    【讨论】:

    • 非常感谢,这听起来是一个很好的线索。我有一个非常忙碌的一周,但我会尽快看看这个。郑重声明,我不是有意识地调用“cancelZoom”,但也许是别的什么触发了它。
    • 嗯,还没有 Android 设备。现在我所能做的就是研究网络上取消缩放的调用。实际上,我认为它不是来自 Modernizr,而是来自这个脚本:gist.github.com/zachleat/2008932 该脚本阻止 iOS 在输入输入字段时缩放页面。
    • 明白了;很公平。当您有时间时,请查看是否禁用它(或删除文件或其他内容)至少可以加快速度。看起来它是一个相当广泛的选择器,所以它是有道理的。
    • 我只是在添加该脚本之前就意识到我遇到了这些性能问题。禁用它似乎没有任何意义。
    • 那太糟糕了;有时间我会再四处逛逛。
    【解决方案3】:

    我相信您的性能问题集中在您的 runMap() 函数中使用 navigator.geolocation.getCurrentPosition()

    if (urlDate != null) {
        urlPos(latitude,longitude);
    } else {
        if (navigator.geolocation) {
            $(".img-loading").show(100);
            navigator.geolocation.getCurrentPosition(successPos, errorPos{maximumAge:600000,timeout:10000});
        } else {
            errorPos('');
        }
    } 
    

    考虑使用watchPosition() 来代替不会停止脚本线程处理的回调。您可以使用 clearWatch() 取消 watchPostion() 更新

    【讨论】:

    • 谢谢,但我的最新发现(见问题编辑)排除了这种可能性。
    • 我添加了一些关于使用 watchPosition() 而不是 getCurrentPosition() 的内容。
    • 谢谢,但很抱歉,这真的不是问题。如果我在 getposition 后发出警报,那几乎是即时的。之后,出现性能问题。与获取用户位置无关。
    • 很公平,但是,根据您对 Edit2 中第 2 步的引用,我怀疑问题是否与数学有关。如果这是较旧的 iOS(4.3 之前),那么可能但 Nitro (JavaScriptCore) 引擎的性能与 V8 和其他引擎相当。我的猜测仍然是它是某个地方的同步阻塞调用,这些极端的性能差异几乎总是如此。希望手动分析会有所帮助。从好的方面来说,如果你确实发现了一个同步调用,你也许可以使用 webworkers 来绕过它。他们在该平台上可用caniuse.com/webworkers
    • 谢谢。今晚我将尝试一起删除位置共享并对位置进行硬编码,作为测试。这绝对应该排除位置检测的问题。
    【解决方案4】:

    所以我又玩了一些,并在 Chrome 上运行了“时间轴”功能(将此文件加载到您的 chrome 时间轴工具中:https://www.dropbox.com/s/2vpl6z1ntuk3aqj/TimelineRawData-20140328T105820.json),看起来这可能是您的主要问题。

    您的脚本和库(包括加载 Google Maps 和 jQuery)在解析 HTML 并运行 Google Analytics 后会得到评估,因为它们位于 body 的底部,而不是 head 的底部。除非您有充分的理由这样做,否则我建议您将其移至 head

    滚动似乎有一个单独的问题,但也许会通过此更改解决。

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-01
      相关资源
      最近更新 更多