首页/文章/浏览器

谷歌浏览器已经是多进程架构,为何在控制台写死循环语句依旧会卡死呢?

2024-08-31
20927 分钟
...

之前在分享谷歌浏览器的架构的时候,结合查到的资料来看,给到观众下面的信息:

谷歌浏览器的多进程架构可以解决单进程架构的不稳定的问题。由于进程是相互隔离的,所以当一个页面或者插件崩溃时,影响到的仅仅是当前的页面进程或者插件进程,并不会影响到浏览器和其他页面,这就完美地解决了页面或者插件的崩溃会导致整个浏览器崩溃,也就是不稳定的问题。

被问了那么一个问题,那“为何在控制台写死循环,浏览器依旧会卡死?” 借着这个问题,我们来再进一步研究背后的原因。

1.开发者工具是单独的进程

打开控制台之前

打开控制台之后,多了一个进程,它有自己的进程ID

2.每个Tab是对应一个独立的开发者工具进程

我在掘金的首页和具体博客页都打开了开发者工具,发现任务管理器就拥有了两个DevTools的进程。

谷歌浏览器的开发者工具(Developer Tools)与浏览器的渲染进程(Renderer Process)之间的通信是通过一套复杂的机制实现的,用到的协议是Chrome DevTools Protocol协议

通信的流程

1.开发者工具和目标渲染进程建立WebSocket连接

当打开开发者工具的时候,浏览器会为开发者工具创建一个新的进程,并建立一个到目标渲染进程的WebSocket连接。

2.开发者工具发送请求

用户在开发者工具中执行某个操作(例如,设置断点、检查元素)时,开发者工具会向渲染进程发送一个JSON-RPC请求。

3.渲染进程处理请求,返回响应

渲染进程接收到请求后,会解析并执行相应操作,并将执行结果封装成一个JSON-RPC响应,发送给开发者工具

4.开发者工具更新界面

开发者工具接收到响应后,会更新界面,并将结果展示给开发者。

通信的内容

通过Chrome DevTools Protocol,开发者工具可以与渲染进程进行各种通信,包括但不限于:

  • DOM操作: 获取DOM结构,修改DOM元素的属性和样式。
  • JavaScript调试: 设置断点、单步执行、查看变量值、调用函数。
  • 网络请求: 查看网络请求、修改请求头和响应体。
  • 性能分析: 分析页面加载性能、CPU占用率、内存使用情况。
  • 日志输出: 查看控制台输出的日志信息
  1. 开发者工具 => 设置 => Experiments => 勾选Protocol Monitor

2.更多=> More tools => Protocol monitor

然后,我们就能观察到如下图的内容

经过观察,我决定选择Page.navigatedWithinDocument作为观察点,一会看是否有出现。

测试过程

测试代码如下:

  while (true) {
    console.log(new Date().toISOString());
  }

刚开始的时候,DevTools内存占用空间是230MB,CPU是27.1,开发者工具进程和渲染进程之间通信的内容是五花八门。

随着时间的推移,DevTools内存占用空间升到259MB,CPU是153.6,开发者工具进程和渲染进程之间通信的内容是一致的Runtime.consoleAPICalled

时间来到一分钟之后,DevTools内存占用空间升到545MB,CPU是141.3,开发者工具进程和渲染进程之间通信的内容是一致的Runtime.consoleAPICalled

试图切换到前端tab,点击无反应,这个时候可以认为渲染进程已经卡死了,开发者工具也是不正常了(白屏)。

白屏的开发者工具,如下图

在手动杀掉开发者工具进程后,渲染进程也没救回来,可见这两者都受伤了

尝试打开新的tab,访问新的网站,是正常的

利用任务管理器手动杀掉渲染进程之后,显示崩溃界面

测试结论

1.在控制台写死循环,会卡死当前的渲染进程和开发者工具进程,不会影响其他进程。

2.出现死循环的时候,进程的内存和CPU会不断的攀升。

3.当出现死循环的时候,渲染进程和开发者进程完全被Demo的Runtime.consoleAPICalled通信占据所有带宽, 无法再通信其他内容,可见这两个进程的资源都被死循环语句占用了。

原因分析

1.死循环时,渲染进程的主线程被阻塞

尽管浏览器是多进程的,但是每个进程内部依然存在主线程,当在控制台执行死循环时,这个循环会不断占用主线程的执行时间,导致主线程无法及时响应其他任务,比如处理用户交互。

2.开发者工具无法及时获取更新的数据

在出现死循环的时候,渲染进程的主线程忙着执行循环代码,开发者工具无法从渲染进程那获取更新的数据,渲染进程也无法回应开发者工具的调试接口。

3.开发者工具自身的资源消耗

在不断的死循环之后,开发者工具从渲染进程那共享到大量的log数据,导致自身的存储数据的资源攀升,导致没有更多资源存储新的数据(谷歌浏览器对开发者工具的内存是有限制的)。

本文以开发者工具是单独的进程展开,介绍渲染进程与开发者进程之间的通信,通过实际的观察,研究在控制台写了死循环之后,渲染进程和开发者进程都有怎样的表现,得出死循环导致页面卡死的原因。从本次研究,可以得到下面的结论。

  • 基于浏览器的多进程架构,一个渲染进程的崩溃不会影响到其他渲染进程。
  • 在控制台执行死循环时,渲染进程的主线程都在忙着执行JS,无法响应其他交互。
  • 渲染进程与开发者工具进程是通过Chrome DevTools Protocol协议进行通信的。
  • 渲染进程无法响应开发者工具,以及开发者工具占用的内存攀升,都是开发者工具卡死的原因。

Chrome DevTools Protocol协议

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
浏览器2025-07-30
浏览器内核到底有哪些?它们各自又有什么区别?
这问题其实很多刚入行的同学经常搞混,所以今天我来一次性讲明白—— 浏览器内核 到底有哪些?它们各自又有什么区别? 说白了,浏览器内核就是浏览器的大脑,分两部分: 渲染引擎(Rendering Engine) :负责网页的排版渲染,HTML、CSS统统交给它。 JS引擎(JavaScript Engine) :处理JavaScript脚本逻辑,比如你点按钮后弹出对话框这种行为。 1)常见浏览器内核盘点 下面我直接列几个主流的浏览器内核,顺...
学习面试
浏览器2025-03-07
浏览器缓存及优化手段
前言 当我们通过url首次访问某个网站的时候,我们如果使用浏览器的工具查看网络请求,会发现有很多http请求,但是当我们下一次再访问时,这些请求都不会发送而是展现在了页面上,而这就是浏览器缓存发挥的作用。 浏览器缓存 浏览器缓存是指将页面长时间不更新的资源缓存到浏览器上,下次访问页面时该部分长时间不更新的资源直接从缓存中获取,从而减少了网络请求次数,提高了页面的加载速度。浏览器的缓存方式主要分为两种: 强缓存 和 协商缓存 ,下面将为大...
学习面试
浏览器2024-12-16
chrome调试工具overrides调试代码
利用Chrome开发者工具断点调试功能调试修改代码,一刷新就什么都没有了,且只能调试JS代码,太尴尬了。 想刷新后,原来修改调试的的代码还在,且JSP、JS、CSS等能调试,那赶快试试下面这种方法吧。 第一步: 在浏览器开发者工具中打开下面的面板sources overrides! 第二步: 打开Select folder for overrides,选择要存放代码的文件夹 第三步: 点击允许访问文件夹,overrides生成刚才选择的...
学习
浏览器2024-09-13
震惊!🐿浏览器居然下毒
发生什么事了 某天,我正在愉快的摸鱼,然后我看到测试给我发了条消息,说我们这个系统在UC浏览器中有问题,没办法操作,点了经常没反应(测试用得iPhone14,是一个h5的项目)。我直接懵了,这不是都测了好久了吗,虽然不是在uc上测得,chrome、safari、自带浏览器等,都没这个问题,代码应该是没问题的,uc上为啥会没有反应呢?难道是有什么隐藏的bug,需要一定的操作顺序才能触发?我就去找了测试,让他重新操作一下,看看是啥样的没反应...
学习
浏览器2024-09-10
深入理解浏览器的事件循环机制
在现代Web开发中,JavaScript作为浏览器中最常用的编程语言,其执行机制深刻影响着Web应用的性能和用户体验。事件循环(Event Loop)作为JavaScript处理异步操作的核心机制,是理解JavaScript执行模型的关键。本篇文章从多个维度去分析事件循环的机制,希望可以帮大家更加深入的了解它。 在讨论事件循环之前,理解浏览器的执行环境是至关重要的。浏览器是一个多线程环境,包含以下主要线程: GUI 渲染线程(GUI R...
学习面试
浏览器2024-09-02
优化浏览器渲染主线程的 api 都有哪些?怎么用?
为了提高浏览器的性能和用户体验,现代浏览器采用了一些技术来优化主线程的执行。主要有: setTimeout 延迟加载 (使用不当可能适得其反) web worker 多线程 (不能操作dom,主要计算密集型的任务) requestIdleCallback 帧空闲时运行 (react18带🔥的,低优先级任务) requestAnimationFrame 每帧都会运行 (主要做动画效果调优) setTimeout 延迟加载非常常见,但是它...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录