浏览器底层,内存分配,运行机制
浏览器底层
今天记录一下新学到的知识,浏览器底层原理,这是一条故事线,我们从双击谷歌浏览器开始。
- 打开浏览器后,操作系统分配内存给浏览器。
- 浏览器拥有多个进程
浏览器进程:
1 Brower 浏览器自身的一些功能
2 GPU 处理不同tab的内容渲染到统一显示区域
3 Renderer tab页内的网页展示,js代码运行在此进程
4 Plugin 控制网页使用的所有插件 - 我们没开启一个tab就会创建一个Renderer进程,如何验证?
我们同时按住shift + esc 打开任务管理器
从图中可以看到百度和知乎有不同的进程ID,我们思考一下浏览器这样设计的意义在哪里?当然设计者有自己的想法,我简单聊一聊我们浏览器的同源策略。我们从进程开始说起,我们在操作系统的书上可以了解到进程是资源分配的最小单位,资源有很多了,比如磁盘,内存等等,这时候我们来关注内存,可以从上面这句话知道,每一个进程之间的内存是相互独立的,并且每一个进程中的线程是共享内存的。如果知乎和百度在同一进程中,我们在百度的tab上通过网络请求回来的数据,知乎也能够读取到,这样就违背了我们的同源策略,所以每一个tab会开启不同的进程。浏览器为了节约内存,也会把同源的但是不同tab的分到一个进程里面。(这一段是我自己结合然后理解的,欢迎大家的指正)
我们继续浏览器打开的流程
- 我们重点关注Renderer进程,这就是我们所看到的网页区域。它拥有自己的五个线程。这里就是我们面试经常遇到的问题,从url到显示完成。
1 GUI
2 JavaScript引擎
3 定时触发器
4 事件触发
5 异步http请求
1.GUI渲染线程
主要负责页面渲染,解析HTML,CSS,构建DOM树,布局,绘制。重绘回流也会执行该线程,与JS引擎线程互斥,遇到JS代码需要执行时,GUI会被挂起知道任务队列为空。
2.JS引擎线程
负责处理和执行JS脚本。因为互斥关系,JS不能够堵塞,不能页面会卡顿。这里也会出现一个事件队列的问题,我们的代码有同步任务和异步任务,我们都知道同步任务优先级高于异步任务,除开宏任务中的同步任务,微任务高于异步任务。
- 事件队列,EventLoop
当我们在解析HTML的时候,遇到JS脚本,首先看是否拥有defer和async属性。这里的执行阶段与DOM解析阶段一定是互斥的,但是加载不用互斥,因为加载是浏览器进程完成的。
1 如果没有,阻塞GUI,开始加载并执行JS脚本;
2 拥有async,异步加载与执行JS脚本;
3 defer同样异步加载,但是会在DOM元素解析完成之后执行JS脚本。
引用一张别人大神的图片
说回事件队列和事件循环,在执行JS阶段的时候,这时候会出现同步任务和异步任务(ajax,
微任务:promise,process.nextTick(node))
宏任务:setTimeout,setInterval,I/O,setImmediate(node)
遇到异步任务之后会将该任务添加到异步队列中并不会立即执行。待全部的同步任务执行完毕之后,来到异步任务队列,这个时候就会根据宏任务和微任务来判断哪一个任务优先执行。在每次执行完宏任务之后,会去清空微任务。
会优先执行微任务,然后在执行宏任务。执行完之后GUI线程渲染。这个时候会不断的去事件队列取出任务,直到为空为止。
一定要自己深入去想,事件队列是跟事件有关系的,是指的在那同一刻是按照这样的顺序执行。
这里我们还能看到一个ajax,我们查不到他的资料,他到底是宏还是微?我们做一个思考,ajax的请求和响应是有时间的1.5个RTT的三次握手,然后传输数据,会耗时,这个时候JS引擎执行宏微时,任务队列并没有把其添加进去。不太理解这个地方,需要查阅更多资料。
3.定时器线程
负责处理异步定时器,JS引擎遇到定时器后,交给该线程,计数完毕后将回调任务添加到事件队列末尾等待JS执行。
4.事件触发线程
将准备好的事件交给JS引擎执行,定时器回调,用户触发的事件,ajax请求的回调。
5.异步http请求线程
负责异步请求,promise,ajax等,异步请求返回结果时,将回调函数加入到任务队列末尾,等待JS执行。
接下来我们来完成面试官的考题相信大家就会很清楚了,url地址输入后,首先要做的就是把域名变成ip地址,我们会先到浏览器缓存中查看是否有该域名对应的资源。这个地方又会涉及到一个新的问题就是浏览器缓存,通常指的是协商缓存和强缓存,强缓存会在上一次响应头中检测到cahe-control:max-age=31536000,public,immutable,根据时间判断此次的请求是否使用该缓存,如果超时,就会下一步协商缓存。如果是协商缓存响应头
etag: ‘5c20abbd-e2e8’
last-modified: Mon, 24 Dec 2018 09:49:49 GMT
,这时候就会去host文件中查找域名和ip地址的对应关系,如果没有就本地DNS服务器解析,如果也没有就去更外层的DNS服务器解析,解析完成之后我们拿到ip地址就可以发起http请求了(首先三次握手,http请求响应,四次挥手)。根据http版本的不同我们会有不同的传输方式,http1.0是短链接,一般来说,一次http请求响应就会经历三次握手四次挥手,http1.1改进了加入了keep-live机制,在约定下传输的时间或者传输http个数,时间或者个数一到就会四次挥手。http2 有更大的改观,使用了头部压缩,二进制帧传输,多路复用的技术,让请求响应速度加快。我们拿到对应的html,css,js之后,我们的浏览器开始了渲染工作,从解析html,css,到遇到js脚本后挂起,执行完js后在继续解析(可能会导致重绘,回流),解析完成之后,就要利用GUI线程渲染我们的页面了,但是我们页面可能使用了z-index属性,这个时候,GPU进程就会帮助我们叠加这些不同的渲染层,让我们看到最终的效果。如果没有请求了,http连接也会断开。
终于来到最后一个部分了,内存的分配
我们来看看JS和汇编的联系。
我们大部分人都知道JS有8种类型,7种基本类型(undefined,null,Number,String,Boolean,Symbol,BigInt),1中引用类型(Object),也都知道基本类型的数据存在于栈区,引用类型的地址存在栈区,内容存在堆区中,那我们的函数他是如何存储的呢?它肯定是引用类型,用函数名 instanceof Object 得到true
在汇编语言中,我们的内存主要分为
代码段:执行代码的一块内存
数据段:静态内存,已初始化的变量
BSS段:静态内存,未初始化的变量
堆:动态分配的内存段,大小不定
栈:存放局部变量
那我们的JS怎么办呢?前面说过,Renderer进程有有一块自己的内存,我们知道JS引擎是在Renderer进程中的一个线程,那这个JS引擎就会分配和使用这一块内存,就会用来存储我们的变量,代码执行等等。和汇编书中讲的还是有一些差别。
主要分为:
- ECstack 执行环境栈,负责代码的执行区域。
- EC 执行上下文,区分不同的作用域
- VO 存储变量的空间,全局上下文
- AO 存储变量的空间,私有上下文
在这里就会产生一个问题,如果我在自己的作用域中并没有找到改变量怎么办?我们就会根据作用域向外部一层一层查找直到找到为止,这就是作用域链。
写不完了,要吃饭了。吃完继续写。
浏览器底层,内存分配,运行机制相关推荐
- Yarn 内存分配管理机制及相关参数配置
理解Yarn的内存管理与分配机制,对于我们搭建.部署集群,开发维护应用都是尤为重要的,对于这方面我做了一些调研供大家参考. 一.相关配置情况 关于Yarn内存分配与管理,主要涉及到了ResourceM ...
- Gstreamer 内存分配协商机制
在两个衬垫的caps协商完成之后,元件之间需要确认如何分配buffer.本文梳理Gstreamer 内存协商机制,比如当某元件不能自己分配内存时,如何使用其他元件的分配器. 场景和目的 一般而言,内存 ...
- 膜拜大佬!JVM性能调优——JVM内存模型和类加载运行机制
一.JVM内存模型 运行一个 Java 应用程序,必须要先安装 JDK 或者 JRE 包.因为 Java 应用在编译后会变成字节码,通过字节码运行在 JVM 中,而 JVM 是 JRE 的核心组成部分 ...
- JVM内存模型和类加载运行机制
JVM内存模型和类加载运行机制 JVM内存模型 运行一个 Java 应用程序,必须要先安装 JDK 或者 JRE 包.因为 Java 应用在编译后会变成字节码,通过字节码运行在 JVM 中,而 JVM ...
- 内存分配算法java_被说烂了的Java垃圾回收算法,我带来了最“清新脱俗”的详细图解...
一.概况 理解Java虚拟机垃圾回收机制的底层原理,是系统调优与线上问题排查的基础,也是一个高级Java程序员的基本功,本文就针对Java垃圾回收这一主题做一些整理与记录.Java垃圾回收器的种类繁多 ...
- 计算机可用内存分配失败,你们都被忽悠了! 其实可用内存大才有用
[PConline 杂谈]随着这几年安卓手机的硬件快速升级,手机的运行内存(本文后续页面将"运行内存"简称为内存或者RAM)也越来越大,从最初的512M到1GB,再到现在主流的2G ...
- JVM源码简析(楔子)-对象内存分配过程和PS回收器中YGC触发FGC的现象
前言 想要搞明白Java对象内存申请过程的原因,是因为第一次接触线上GC日志的时候,发现了一些很奇怪的现象,就是young gc触发了full gc.为了搞清楚这个现象,得先要来个测试去复现. 复现现 ...
- 深入理解JVM内存分配策略
点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长 每天早上8点20分, 第一时间与你相约 每日英文 Don't blame people for disappointing ...
- C++中运行一个程序的内存分配情况及qt中的内存管理机制
一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 2.堆区(heap) - 一 ...
最新文章
- UE4入门学习3:GamePlay框架
- java基础 --- Arrays.asList():返回指定数组支持的固定大小列表
- (办公)eclipse连接github cannot open git-upload-pack(git-receive-pack)
- 实现一个闹钟_iOS 14 闹钟:为啥这么难用?
- GPS NAME0183 详解
- 《Redis开发与运维》学习第四章
- 强化学习入门笔记(一)——莫烦Python
- PATHLOSS.4.0 无线电设计软件
- 2018WPS暑期实习生web前端笔试题
- 最新软件注册码,总有你要的!
- 【python技能树】python程序设计思想
- 宁皓网bootstrap
- 执念斩长河专栏总目录
- PAT基础级-黄金段位样卷1
- 算法:(二)枚举(穷举)算法
- 安装、卸载mysql服务命令
- 六种常见的「用户行为」分析方法
- 在线压缩转换文件的软件
- C/C++浮点数的存储方式 IEEE-754标准,以及实现一个ftoa函数将浮点数转换为字符串
- 面向万物智联的应用框架的思考和探索(上)