settimeout性能,settimeout会阻塞吗

作者:YJ 转发链接:https://mp.weixin.qq.com/s/4P7ohpRmBChXQpLC-MHgHQ

Why\’s THE Design 是关于计算领域,尤其是前端领域的编程决策的系列文章。本系列将讨论此设计的优缺点的各个方面以及对您的具体实施的影响。灵感来自Draveness 的《为什么这么设计》

正文在前端技术社区,关于setTimeout的一个共同结论是setTimeout的最小设置延迟为4ms。根据“不知何故”定律,在回答问题之前,必须先“检查是否属实”,然后“检查是否属实以及为什么”。

我们先来看第一个问题。 “是否有具体的规范规定4ms?或者这只是行业惯例的既定事实?”

熟悉前端的人都知道,setTimeout 不是由ECMAScript 维护的,而是由主机环境提供的。某些需要遵循的规范由Whatwg 维护(ECMAScript 不直接提供setTimeout 函数有很多原因)。在2011 年Esdiscus 讨论中,参与者包括Brendan Eich、Kyle Simpson 和一群老年人。我将在稍后或在另一篇文章中简要讨论这一点)。回到HTML标准,setTimeout()和setInterval()在8.6 Timers-2023/6/23中有详细解释。这里我们只看第10-13 行。

如果超时时间小于0,则将超时时间设置为0。

如果嵌套层数大于5且超时小于4,则将超时设置为4。

将嵌套级别增加一级。

将任务计时器的嵌套级别设置为嵌套级别。

这可以从上面的规格中看出。

如果配置的超时时间小于0,则将其设置为0。如果嵌套层数超过5层且超时时间小于4ms,则将超时时间设置为4ms。至此,我们似乎找到了4ms的原因,让我们对setTimeout的最小延迟有了更精确的定义。 “只有嵌套层数超过5层且超时时间小于4ms时才设置4ms。”

您可能想知道“计时器的嵌套级别是多少?” (我也很感兴趣),更多信息请看下面的代码(后面我会通过chromium源码解释如何在浏览器源码中实现定时器嵌套级别和最小延迟)。

setTimeout(()={setTimeout(()={setTimeout(()={setTimeout(()={setTimeout(()={},0)},0)},0)},0)},0)希望这能解释setTimeout 最小延迟的设计。但B站有句俗话:“你只看二楼,以为我在一楼,其实你已经到了五楼。”

当我看到一群朋友提出这个问题时,我的第一个想法是,除了寻找规范的来源之外,我还有两个担忧。

各大浏览器制造商是否按照规范来实现?如果没有,为什么?4ms这个数字到底是如何确定的?这个根源可能来自于设计结果的挑战、背景和限制。我们需要了解的不仅仅是设计。最重要的是,您需要了解设计背后的内容。 ” – 例如,大型科技巨头和制造商如何在幕后竞争和权衡。

首先我们看一下各种主流浏览器在不同边界条件下对于setTimeout延迟的输出(这里不考虑由于单个事件循环的延迟而导致的setTimeout延迟的增加,并且在最原始的情况下也不考虑) (注意,这是一个简化)具体来说,不考虑单循环执行(假设单循环执行时间在ms级别以下,时间太长的情况):

Chrome 83.0.4103.106 和Safari/edgeFirefox 65.0.1 和IE 11。从上图可以看出,各大浏览器厂商对于setTimeout配置延迟分别采用了0毫秒和1毫秒两种策略。具体策略可以在浏览器源码中找到(我这里只展示chromium源码;其他Webkit或者Firefox可以自行下载查看)。该程序位于chromium flash 目录中。 DOMTimer .cpp 文件称为在线地址。您还可以在此处设置计时器延迟。

staticconstintmaxIntervalForUserGestureForwarding=1000;//One SecondmatchesGecko.staticconstintmaxTimerNestingLevel=5;staticconstdoubleoneMillisecond=0.001;//Chromium使用最小定时器间隔为4ms。 //我想降低它,但是有一个编码很差的网站//创建了一个CPU旋转循环。使用4 毫秒可以防止CPU 过度旋转,并在CPU 旋转和尽可能小的间隔计时器之间取得平衡。 staticconstdoubleminimumInterval=0.004;doubleintervalMilli Seconds=std:max(oneMilli Second,interval*oneMillisecond);if(intervalMilliseconds=maxTimerNestingLevel)intervalMilliseconds=minimumInterval;代码的逻辑很清晰,有三个常量:

最大定时器嵌套级别=5。即HTML标准中提到的嵌套级别minimumInterval=0.004。这是HTML标准中提到的最小延迟。在第二段代码中,可以看到在延迟时间和1ms之间首先获得了最大值。即如果不满足嵌套级别,则最小延迟时间设置为1ms。这也解释了为什么在Chrome 中测试setTimeout 会给出上述结果。

chromium的评论解释了设置minimumInterval=4ms的原因。简而言之,Chrome 团队想要低延迟(事实上,他们希望达到亚毫秒级)。然而,一些网站(例如纽约时报)没有正确使用setTimeout 计时器。网站),设置太高的延迟会导致CPU 自旋(稍后我们将解释什么是CPU 自旋),因此chromium 运行了一些基准测试并决定使用4ms 作为所选的最小间隔。

至此,我们从浏览器厂商和HTML标准规范的角度解释了4ms的由来和更精确的定义。但人们会好奇这个设置是首先由HTML 标准还是由Chromium 等浏览器制造商完成的。理解序列的重要性在于理解它们背后的历史以及规范和制造商如何相互促进和平衡。

首先,让我们仔细看看操作系统层面。 Windows中默认的定时器分辨率是10-15.6毫秒(这里理解为定时器粒度)。也就是说,浏览器定时器依赖于最初的定时器。操作系统级分辨率。如果切换到setTimeout,最小延迟设置将至少为10ms。然而,在CPU性能方面,虽然处理器速度从1995年的500HZ提高到3GHZ以上(2010年达到),但Windows中的默认计时器没有改变,仍然是原来的10-15.6毫秒(浏览器制造商和操作系统)。厂商从不同的角度思考)。浏览器制造商(Chrome)认为默认计时器影响网页的呈现(10-15.6毫秒太长)。在浏览器内部,如果时钟滴答声很长,则意味着浏览器休眠了很长时间,这在某种程度上导致浏览器性能变慢。

上面的讨论指出了一个既定的事实,即windows下所有浏览器中定时器的实现最初依赖于操作系统定时器(10-15.6毫秒)。实际测试结果是基于Erik Kay的可视化排序测试和John Resign(著名JQuery作者,可以看出大佬们对基础层有自己的理解)简单的测试方案,特别是John Resign的文章,可以看下在2008。

Chrome 非常重视10 到15.6 毫秒之间的计时器。我们知道,Chrome 的目标是成为一款高性能、现代的浏览器,特别是在计时器分辨率方面,其目标是亚毫米分辨率(小于1 毫秒)。因此,Chrome团队想要改变浏览器对操作系统定时器的依赖,并在Windows和Linux/UNIX系统上采用了多种解决方案来实现他们的目标。 Linux/unix 有专门的API 用于更改系统默认计时器分辨率,但在Windows 上则有点麻烦,最终chromium 团队决定使用与Flash 和Quicktime 相同的API 来替换所选的系统默认计时器分辨率。

更改操作系统默认计时器分辨率后,Chrome 的性能显着提高。具体到Chrome 1.0 beta,计时器分辨率设置为1ms(已经接近团队预期)。有人可能会问,既然追求低延迟,难道不就设置成0ms吗?

原因是如果浏览器允许0ms,JavaScript引擎就会过度循环。这意味着,如果您的浏览器具有单进程架构,您的网站可能会变得响应速度较差。浏览器本身也是构建在事件循环之上的,因此如果一个缓慢的JavaScript 引擎不断通过0ms 计时器唤醒系统,它将阻塞事件循环。那么,用户此时会面临什么情况呢?同时经历CPU 旋转和基本浏览器挂起是令人沮丧的。很少有人愿意利用用户经常遇到这种情况的浏览器。这就是为什么Chrome 1.0 beta 设置为1ms。

结果看起来非常好,但随后有几个团队报告了错误(具体来说有两个,一个是前面提到的《纽约时报》网站错误,另一个是英特尔团队发现了chrome 异常的功耗)。我发现定时器导致CPU旋转,并且由于CPU旋转,计算机无法进入睡眠模式(低功耗模式)并且耗电非常快。因此,Chrome 团队必须解决一个真正的问题(他们不想变得太大,因为Chrome 的市场份额没有今天那么大)。 Chrome 团队当时的计划是对计时器设置很多限制。 Chrome团队随后进行了一些实验,发现将1ms增加到4ms可以解决大多数机器上的CPU旋转和功耗过高的问题。这种权衡实现了Chrome 团队的目标,即在不引入额外问题的情况下实现更准确的计时器。

顺便说一句,Chrome 团队最初实际上是在与Windows 团队沟通,希望Windows 能够提供动态调整硬件时钟间隔的能力,以满足更高层应用程序的需求,结果沟通不太顺利。这可以从微软曾经发表的一次关于为什么他们不愿意做出这样的改变的演讲中得到理解。在那次演讲中,他希望未来的操作系统能够强制降低唤醒速率(100ms),以减慢许多应用程序的启动速度。不当行为。换句话说,Chrome团队的期望和Windows团队的期望是矛盾的。至此,你应该明白了,不同的团队对于同一件事有不同的考虑。

Chrome团队调整了定时器(显着提高了性能)后,其他主流浏览器如(Safari、Opera、Firefox、IE)都采用了4ms设置,并且每个浏览器的定时器节流在不同的条件下运行(这是为什么。为什么我的。)使用不同浏览器的第一次测试会给出不同的结果?)后来HTML标准制定了相关规范。

事实上,定时器分辨率并不是一个经常讨论的话题(因为它需要大量的基础知识,而且往往是低级的),但事实上定时器分辨率是在不断被开发的。

正如Nicholas C. Zakas 在他的一篇文章中所说,“我们已经接近可以将浏览器控制到毫秒的程度。如果有人弄清楚如何在不中断CPU 的情况下管理定时器,定时器就会出现。”在此之前,请记住4 毫秒。但是,请记住,您并不总是能得到这一点。 ”

总结一下,可以看看4ms的setTimeout是如何设置的。此方法允许您更精确地定义最小延迟。

不同的浏览器有不同的最小延迟。例如,Chrome的最小延迟是1ms。另外,如果定时器嵌套层数较多,则最小延迟为4ms。具体的嵌套级别阈值因浏览器而异。 HTML标准是5,Chrome是=5。此外,我们了解上述两个问题。

各大浏览器制造商是否按照规范实施?为什么?每个主要浏览器制造商都使用自己的基准,因此并没有完全按照规范实施。规格。此外,HTML 标准提供了适应变量的灵活性,且影响很小。我们还了解4ms 背后的背景、浏览器和操作系统制造商背后的各种考虑因素以及每个解决方案的决策和权衡。

推荐JavaScript 学习

本文和图片来自网络,不代表火豚游戏立场,如若侵权请联系我们删除:https://www.huotun.com/game/644021.html

(0)
上一篇 2024年5月29日
下一篇 2024年5月29日

相关推荐

  • 和平精英如何获取永久套装?

    和平精英如何获取永久套装? 目前还不能获得永久版的,只有30天使用权。;和平精英;完美勇士套装是属于期限套装,以后会不会上架或者做活动放出来就不知道了。 和平精英永久买皮肤真的? 是真的,和平精英可以永久买皮肤,一次性购买,永久使用 免费领皮肤永久和平精英? 那也只是骗人的而已,连最起码的黑色伏地魔都要600个服饰币,可以免费领永久的皮肤都是假的,除非你有申…

    游戏快讯 30分钟前
  • 和平精英如何画车皮? 和平精英手册如何画?

    和平精英如何画车皮? 车皮可以通过以下步骤进行绘制:1. 打开和平精英游戏,在游戏主界面进入“武器”选项,选择需要绘制车皮的武器,点击“皮肤”选项;2. 在皮肤选项中,选择“全部”,之后会弹出所有该武器的车皮和皮肤,选择一个自己喜欢的车皮;3. 点击该车皮后,可以在下方看到该车皮的款式,还可以选择自己喜欢的颜色;4. 点击“图案”选项,这里提供了多种图案,可…

    游戏快讯 1小时前
  • 和平精英下赛季更新内容?

    和平精英2022年6.29更新内容一览 版本更新奖励 6月29日-7月4日活动期间更新版本即可获得: 科学之轮宝箱x1、金币x3888、双倍金币卡x1(3日)、双倍经验卡x1(3日)。 主要更新内容 全新版本主题玩法 – 科学之轮 活力四射的夏日又到啦!这一次,冒险世界将以科技为主题,打造全新的战斗区域和互动玩法!特种兵们,还等什么?快来一决高下…

    游戏快讯 3小时前
  • 和平精英极限追猎模式免费得机甲?

    和平精英极限追猎模式免费得机甲? 怎么知道和平精英极限训练模式? 他们都是有晶体来自取获得机甲的,所以如果我们想获得,可以通过我们的技术来击杀敌人,获取也可以再靠自己的运气去地上捡,这样都是可以的,因为剂的作用是可以使我们变得更加厉害,也可以使我们的技术提高 和平精英怎么刷机甲? 和平精英刷机甲的地点是不固定的,机甲是系统自动刷的,不是人工刷的,要想了解刷机…

    游戏快讯 4小时前
  • 和平精英怎么练狙? 准度怎么练和平精英?

    和平精英怎么练狙? 的方法很多,但是要想更快的提升技能,建议可以:1.多实战多比赛:熟悉游戏场景,不断练习,多多熟悉其中的规则,不断积累,改善狙击技术。2.在宽包围环境进行练习:在宽敞的户外环境时,可以帮助更好的理解狙击枪的特性以及如何运用狙击技术的技巧。3.练习准心瞄准:学会准心瞄准,练习提高精准瞄准技能,这是发挥狙击枪的基本技巧。4.多参加比赛:经常去参…

    游戏快讯 7小时前