70场面试,复盘我遇到的有趣问题(七)

       本系列到第七期了,这一期和下一期都来看一下灵犀互娱二面遇到的一些问题。二面过程中的技术问题不多,但是个个都深入原理,而且由于灵犀互娱这边是游戏公司,所以涉及到很多渲染优化的知识点,因此能够学习到很多原理。
       涉及到原理的部分我的理解比较有限,大家看的时候辩证的看哈。
        今天我们就看一个问题吧。
Q:浏览器渲染原理是怎么样的,gpu进程和渲染进程之间如何协调配合,如何通信?
       在问这个问题之前,面试官问了一个大家都被问过的问题:url输入到渲染全流程。没错,整个渲染全流程大家基本都知道,但是想要回答后面的问题就需要更加细致的了解中间的一些概念(先来背一遍进程和线程的概念)。
       (面试过程肯定不用说下面这么多,但是我觉得借此机会了解整个过程还是很重要的,知道全过程才能用自己的语言描述出来,并且也不怕面试官详细到某个点)
       首先来回顾一下浏览器的多进程架构。浏览器的四个主要进程是主进程、第三方插件进程、GPU进程和渲染进程,其中主进程只有一个,负责浏览器界面显示与用户交互,负责各个页面的管理,创建和销毁其他进程等等;第三方插件进程有多个,每种类型的插件对应一个进程,仅当使用该插件时才创建;GPU进程最多一个,与其他进程隔离处理 GPU 任务,用于加速绘制;渲染进程(也就是我们常说的浏览器内核Webkit等)有多个,默认每个 Tab 页面都会产生一个渲染进程,互不影响,他的内部是多线程的,渲染页面、脚本执行之类的就靠他。
       其中渲染进程有五个主要线程:1.GUI 渲染线程:负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。需要注意的是GUI 渲染线程与 JS 引擎线程是互斥的。2.JS 引擎线程:JS 引擎线程负责解析 Javascript 脚本,运行代码。JS 引擎一直等待着任务队列中任务的到来,然后加以处理,一个 Tab 页(renderer 进程)中无论什么时候都只有一个 JS 线程(单线程)在运行 JS 程序。3.事件触发线程:他不受JS引擎线程控制,主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数添加进任务队列中,等待JS引擎线程空闲后执行。4.定时器触发线程:也就是setTimeout,setInterval所在的线程。浏览器的定时器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响计时的准确,因此通过单独的线程来计时并触发定时器,计时完毕后,满足定时器的触发条件,则将定时器的处理函数添加进任务队列中,等待JS引擎线程空闲后执行。5.异步HTTP请求线程:当HttpRequest连接后,浏览器会新开的一个线程,当监控到readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进任务队列中,等待JS引擎线程空闲后执行。具体这些线程之间的关系从帖子中找了个图(图1)
       然后我们看下渲染原理。浏览器接收到返回的html之后就会开始渲染流程,输入的 HTML 经过一些子阶段,最后输出像素。看看图2,有整个渲染过程。
       这个过程涉及到渲染进程中的主线程,合成线程和光栅线程池。
       主线程:1.浏览器接收到HTML后,主线程开始解析HTML并转为DOM结构,在这个过程中,如果遇到script标签会挂起渲染线程,让js线程进行解析,因此script标签会阻碍DOM的解析。2.DOM解析完成后会进行CSS解析,计算样式,在计算过程中需要遵守 CSS 的继承和层叠(层叠的规则不记得的回去抄书)两个规则,这个阶段会构建CSSOM树。3.有了DOM树和CSSOM树就要创造渲染树了,因为有了DOM和component style(每个元素对应的样式)之后还不足以绘制页面,需要知道每个元素的位置和几何属性,这个阶段叫做布局(Layout)。4.有了渲染树之后,由于CSS中有复杂的效果,以及各元素之间有z-index等层级关系,因此下一步是分层。对于这些场景为了页面展示的正确性,渲染引擎还会为特定的节点生成专用的图层,并生成一棵对应的图层树。5.有了渲染树,图层树之后,主线程会遍历这些树并确定一个绘制顺序,创建绘制记录。
       合成线程:分块,光栅化,合成。上面主线程的步骤走完之后,会将信息提交给合成线程,合成线程中会走光栅化(栅格化)这个步骤。什么叫光栅?大家可以搜一下,就跟栅栏一样,很多很多狭小的缝隙,那么光栅化的过程其实就是把整个页面分割成很多很多小的块去处理。为什么要进行这个处理,就是因为页面很长的时候,用户只能看到视口内容,有些图层可能超过视口很多,一次性渲染整个图层未免有些浪费,因此合成线程会对图层进行分块处理。栅格化之后,每一块会送给光栅线程池中的一个线程。合成线程的最后一个过程就是合成,会创建合成帧通过 IPC 通信(进程通信)提交给浏览器进程。浏览器进程接收到指令后会将内容绘制在内存中并展示在屏幕上。
       光栅线程:上面提到光栅线程要去处理每个块,这个阶段会和GPU进程进行通信协调,会光栅化每一个图块并存在GPU内存中。
       至此,浏览器渲染的完整原理就完全结束了(里面还有很多细节,这里帖一个参考帖:https://segmentfault.com/a/1190000041840526#item-2-8)。到这里也基本可以回答“gpu进程和渲染进程之间如何协调配合”这个问题了,配合的阶段就在光栅化这一步骤。
       最后就是主进程,GPU进程和渲染进程三者如何通信。浏览器进程收到用户请求,首先需要获取页面内容(譬如通过网络下载资源),随后将该任务通过 RendererHost 接口传递给渲染进程,渲染进程的 Renderer 接口收到消息,简单解释后,交给渲染线程,然后开始渲染。渲染线程接收请求,加载网页并渲染网页,这其中可能需要浏览器进程获取资源和需要 GPU 进程来帮助渲染,当然可能会有 JS 线程操作 DOM(这样可能会造成回流并重绘)。最后渲染进程将结果传递给浏览器主进程。浏览器进程接到结果并将结果绘制出来。
       上面都提到了整个流程,那么从这个流程的角度去理解一下重绘和重排。当我们通过 js 或者 css 属性更新了元素的几何属性会触发重排,此时浏览器会触发图3中布局及以后的所有步骤;当我们通过 js 或者 css 更新元素的绘制属性而不改变几何外观的时候,浏览器会触发图3中绘制及以后的所有步骤。因此重绘的开销相比重排会小很多。
       为什么我们为了避免重排和重绘而去采用 css3 的 transform 等属性呢?因为此时整个主线程的流程会被全部跳过,执行后续的流程,而后续的流程交给了在执行线程、光栅线程和 GPU 进程上执行没有占据主线程的资源,因此效率是最高的。
    
       这个问题到这基本就完整结束了,一个小小的问题,其实考察对于浏览器内核的渲染原理,在被问到之前我自己从来静不下心去看这个只是点,因为实在是低频。但是实习过程中又总是听到其他同时讨论渲染进程的优化问题,直到自己被问到不会了才沉的下气去看这些问题。还是要逼自己多看点东西。
       如果大家觉得有用,欢迎大家点赞收藏关注送花!!!

该系列往期链接:
第一期:https://www.nowcoder.com/feed/main/detail/a79cb52ce00c4f6d874683e65b8eb718?sourceSSR=users
第二期:https://www.nowcoder.com/feed/main/detail/04aee48cc23f4b09a04d0dba327f0c5d?sourceSSR=users
第三期:https://www.nowcoder.com/feed/main/detail/0195906f12dd4fc0826251e9ceee19ab?sourceSSR=users
第四期:https://www.nowcoder.com/feed/main/detail/2c0a525fa04240778e6c43d7d355a7ca?sourceSSR=users
第五期:https://www.nowcoder.com/discuss/673869939018588160?sourceSSR=users
第六期:https://www.nowcoder.com/feed/main/detail/ebead4b4e5da48439388aab5d4be290d?sourceSSR=users
#阿里##灵犀互娱##前端##24届软开秋招面试经验大赏##我的求职思考#
全部评论

相关推荐

1.16一面1. 做题   1. 并行请求网站   2. 查找二数之和   2. golang:GMP  defer执行顺序  并行的实现方式(互斥锁、channel)   3. 项目:Prometheus二开  4. 实习:集群架构+体量  监控方案中的难点thanos持久化5. OSI6. http 方法   7. HTTP 1.1  HTTP 2 的TCP队头阻塞原因,HTTP3优化策略 QUIC   - HTTP 1.0 默认短连接,HTTP 1.1默认长连接,长连接可以处理多个请求,但必须按照顺序处理请求、按顺序返回响应。因此如果在队列中,一个请求由于网络等问题耗时过长,便会阻塞后面的请求。   - HTTP 2 对1.1的优化在于,采用二进制分帧,同时支持多路复用,即在一个TCP连接上处理多个流的传输,但如果某个stream数据丢包,需要等待重传,造成阻塞。   - QUIC 基于UDP;每个流单独传输;内置加密TLS1.3,减少握手延迟     8. https(ssl -> tls)   TLS支持 前向保密性,保护历史通信,应对密钥泄露的情况   加密原理:   - 使用 DHE (迪菲赫尔曼加密)生成一次性的会话密钥;   - 后续升级为 ECDHE(椭圆曲线迪菲赫尔曼加密),使用椭圆曲线算法,优化性能     9. 输入域名后涉及到的协议  10. DNS 查询使用的协议 UDP TCP   UDP和TCP都用到   - 辅助DNS服务器每隔一段时间向主DNS服务器做区传送的时候,使用TCP   - 域名解析的时候追求速度,使用UDP11. 可观测性了解吗12. docker网络模式有哪些13. k8s组件作用  14. 操作系统Linux发行版15. Linux的内核态和用户态    问的挺基础的,答得不好
查看16道真题和解析
点赞 评论 收藏
分享
测试开发面经12.9一面自我介绍项目经历:围绕了项目经历进行提问,比如 具体是做了哪一块,然后就介绍具体做了什么,优化了什么,有具体测试出优化了多少吗。然后根据简历上写的缓存一致性又深入聊了,然后就问我先更新数据库,再删除缓存,这一个是怎么做的,然后如果让我测试这个场景,会怎么设计测试用例。实习经历:然后就围绕实习经历进行提问,怎么找的这个实习,然后就介绍自己印象最深刻的一个项目,以及是怎么测试的,然后就是根据这个不断深挖,深问,问了功能测试是怎么测的,什么是埋点测试和接口测试,具体是怎么做的,怎么决定模拟并发的时候的并发数。游戏经历:根据游戏经历开始问,然后就问最近玩的游戏是什么,或者最想分享的一个游戏是什么,然后我就选择聊了英雄联盟,然后就开始聊了大概十分钟,比如:为什么是觉得想聊英雄联盟?你玩什么位置比较多?为什么喜欢玩打野?你对于打野这个位置的理解是什么?你最喜欢的一个英雄是什么?(我说了蜘蛛)然后就问 你开局的思路是什么,你觉得玩蜘蛛是怎么赢游戏的,节奏是怎么样的如果你是设计师,你会如何设计来加强蜘蛛的打团能力。你觉得英雄联盟这游戏是怎么样的一个状态,未来会是怎么样的?你作为策划你会怎么做来让游戏更多人玩?其他问题:你的获奖经历,可以聊聊你蓝桥杯的获奖是怎么样准备的吗?其中遇到了什么困难?你后续有升学的打算吗?你有别的offer吗?反问:后续流程是怎么样的?游戏测试和软件测试有什么不同吗?体验很好,聊得很开心12.12二面:自我介绍然后围绕了实习经历进行非常细致的提问实习经历:介绍实习做了什么?具体什么业务排行榜这个是怎么测试的?封榜的逻辑是怎么设计的?发奖的逻辑是怎么样的,怎么设计测试用例,要考虑哪些?排行榜具体设计到的数据库表是怎么设计的?都有什么字段?之前那个公司的实习的薪资怎么样?转正的待遇如何?工作强度你觉得怎么样?设计测试用例的时候,leader帮你检查的时候主要是检查或者补充什么部分?有遗漏过什么吗?你觉得测试和测开有什么区别?注重的点是什么?你是怎么理解测试这个岗位,以及为什么想要来干测试?你对于自动化测试怎么理解?你会帮你前公司设计哪些提效的测试工具?如何实现?(聊了很久)如果版本大改,页面变动很大,那自动化的代码不能复用了,你如何处理?如何减小影响?游戏经历:喜欢玩什么游戏?(我答了英雄联盟)对于打野的理解怎么安排前期的野区路线和gank路线野核和节奏型打野这两种类型的打野,你觉得什么因素会影响他们的强弱。面试官问的特别细致,也会给出反应和回应,也会给出一些方向的提示,体验很好网易游戏(互娱)2026届实习生培养项目,2月25日震撼启航!️ 面向26届追梦人,你准备好了吗?如果你是2025年9月至2026年8月间毕业的闪耀新星,这将是你不容错过的舞台!📍招聘城市:广州、杭州、上海招聘岗位:涵盖5大类近40个岗位校招C位提前锁定、SSR级培训资源、一流的实习福利等你来~投递传送门:https://game.campus.163.com/m/home?st=YTE1ZTlhNDUtNmNlMC00ZTI5LWE2ZjUtZGMxNTNhNDhjNzlm内推码:【9QcfNR】内推码可帮助大家优先筛选或直通笔试!!(大家使用这个内推码投递,我才可以帮大家查询进度,跟进流程~) #内推码#                               #校招#                               #暑期实习#                               #内推#                
点赞 评论 收藏
分享
评论
10
24
分享

创作者周榜

更多
牛客网
牛客企业服务