博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浏览器-04 WebKit 渲染2
阅读量:4659 次
发布时间:2019-06-09

本文共 2095 字,大约阅读时间需要 6 分钟。

渲染主循环(main loop)和requestAnimationFrame

requestAnimationFrame

  • 使用requestAnimationFrame而非setTimeout/setInterval绘制动画;
  • requestAnimationFrame:告诉浏览器JavaScript想发起一个动画帧,然后在动画帧绘制之前,需要做一些动作,这样浏览器可以根据需要来优化自己的 mainloop机制和调用时间点,以达到较好地平衡效果;
var start = null;var element = document.getElementById("example");function step(timestamp) {  if (!start) start = timestamp;  var progress = timestamp - start;  element.style.left = Math.min(progress/10, 200) + "px";  if (progress < 2000) {    window.requestAnimationFrame(step);  }}window.requestAnimationFrame(step);

渲染mainloop

mainloop过程

  • chromium是多进程的结构,Browser进程用户界面的mainloopRenderer进程的主线程的mainloop分别位于两个不同的进程,所以UI和渲染可以互相不影响;
  • 但是Renderer进程的渲染工作和JavaScript的执行工作都在其主线程中,由mainloop来负责调度完成,存在竞争;

  • 过程:大的循环加上一个事件队列
    * 当队列中有事件时,从队列中取出第一个事件,设置相应的状态信息,处理该事件及其对应的处理函数,直到该函数处理完后,才重新检查队列中是否有事件;
    * 如果有,继续处理;如果没有,则继续等待;
  • 存在问题:

    * 如果队列中事件多,很多事件可能来不及处理,造成比较大的延时,因而事件的平均等待时间会比较长;
    * 如果事件的处理函数需要的时间很长,就会造成后面的事件一直在等待,同样会增加事件的平均等待时间;

WebKitChromium中的实现

  • setTimeoutsetInterval的实现:
    * WebKit会为DOM中的每个setTimeoutsetInterval的调用创建一个DOMTimer,而后该对象会由存储TLS(thread localstorage)中的 ThreadTimers负责管理,其内部其实是一个最小堆,每次取timeout最小时间,同时,相同的Timer可以合并;
    * 当Timer超时后,Chromium清除该Timer对象,同时调用相应的回调函数,回调函数通常会更新页面的样式和布局, 这会触发relayout,从而触发立即重新绘制一个新帧;
  • setTimeoutsetInterval从不考虑浏览器内部发生了其他什么事,它只要求浏览器在某个时间之后调用它的回调函数,无论浏览器很繁忙或者页面被隐藏;
  • requestAnimationFrame的实现原理就是其会申请绘制下一帧, 时间由浏览器决定,只需要浏览器在绘制下一帧前执行其设置的回调函数,完成JavaScript对动 画所做的设置和逻辑即可;
    * JavaScript调用requestAnimationFrame,相应的webkitchromium会调度一个需要绘制下一证的事件,该事件会将requestAnimationFrame的调用上下文和回调函数记录下来;
    * 上面的请求会触发Chromium更新页面内容的事件,该事件被mainloop调度处理后,会检查是否需要调用动画的相关处理,如果有动画需要处理,就会依次调用那些回调函数,JavaScript引擎会更新相应的CSS属性或者DOM树修改;
    * Chromium触发重新计算layout,更新自己的Renderer树,而后绘制完成一帧的渲染;
  • 为了实现更好的性能,chromium中对requestAnimationFrame有三个设计原则:
    * 当页面不可见时,其回调函数不会被调用,这可以减少CPUGPU的使用率;
    * 其最大调用频率不会超过60hz,无论屏幕的刷新率是多少,;因而回调函数也不会每秒调用超过60次,这是因为60FPS已经能够满足UI流畅的要求了;
    * 只有当页面真正开始渲染时,回调函数才会被调用;

设计机制带来的编程考虑

  • 回调函数不能太大,不能占用太长时间,否则会影响页面的响应和绘制的频率;
  • requestAnimationFrame不需要设置间隔时间,不同刷新率的间隔时间不一样,这完全由浏览器来控制,而不需要操心;
  • 回调函数无需合并,可以在任意位置设置回调函数,它们可以被浏览器集中处理, 而无需要一个统一的入口;

转载于:https://www.cnblogs.com/jinkspeng/p/5040067.html

你可能感兴趣的文章
linux文件的隐藏属性:chattr
查看>>
【原版的】PHP技术成长规划过程中猿人
查看>>
NTP工作机制及时间同步的方法
查看>>
近段时间学习html和CSS的一些细碎总结
查看>>
学习Coding-iOS开源项目日志(一)
查看>>
第三章 栈和队列
查看>>
WPF 自定义NotifyPropertyChanged
查看>>
全排列算法
查看>>
「Vue」v-html生成的图片大小无法调整的解决办法
查看>>
为什么要使用SLF4J而不是Log4J
查看>>
codeforces 959E Mahmoud and Ehab and the xor-MST(找规律)
查看>>
Extjs win
查看>>
Java----线程协作的经典例子&生产者和消费者问题
查看>>
noip模拟赛 第k大区间
查看>>
Windows 配置vscode
查看>>
Linux内核分析-系统中断在内核中的实现
查看>>
(第四天)作用域链、闭包
查看>>
杭电个人排位赛第三场
查看>>
运用iscroll.js遇到的问题
查看>>
嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比
查看>>