浏览器进程,性能指标

53 篇文章 14 订阅
4 篇文章 0 订阅

目录

浏览器进程:多进程

主进程:显示、交互,增删进程

UI进程:控制地址栏、书签、前进后退

存储进程:cookie,webstorage,indexDB

渲染进程:每个标签页或窗口都有一个独立的渲染进程,解析HTML,执行js

插件进程

GPU进程:图像渲染

网络进程:请求

LightHouse:性能分析工具(v8/v9性能指标)

Opportunities优化建议列表

Diagnostics 诊断问题列表

FCP首次内容绘制(First Contentful Paint)⭐

优化手段:缩短字体加载时间

LCP最大内容绘制(Largest Contentful Paint)⭐

原因

缓慢的服务器响应速度

阻塞渲染的 JavaScript 和 CSS

缓慢的资源加载速度

客户端渲染

首次像素绘制 FP(First Paint)白屏⭐

从输入 url 开始:dns 、tcp 、http请求、返回 html 文档、html 文档解析

CLS(Cumulative Layout Shift):累积布局偏移,(衡量网页元件视觉稳定性)⭐

CLS 较差的最常见原因为:无尺寸、动态注入

优化手段

1. 除非是对用户交互做出响应,否则切勿在现有内容的上方插入内容

2. 倾向于选择transform动画

TTI(Time to Interactive):变成完全交互式的时间

TBT(Total Blocking Time):阻止响应时间

长时间任务(Long Tasks): 长时间任务是指在浏览器主线程上执行的任务,其持续时间超过50毫秒(通常)

后果:这可能会阻塞其他任务的执行,包括用户输入响应,JavaScript脚本的执行、DOM操作、CSS计算等。

SI(Speed Index):帧之间的视觉进展

优化手段:减少主线程工作 、JavaScript的执行时间

首字节时间:网络后端的整体响应耗时

window.performance API

性能统计

Level 1 的规范(window.performance.timing)

level2规范(performance.getEntriesByType('navigation')[0])

确定统计起始点

fetchStart:准备好使用 HTTP 请求获取文档

浏览器重定向、卸载页面的耗时对页面加载分析并无太大作用;通常使用 fetchStart 作为统计起始点。

性能数据计算公式

使用 performance.timing 简单计算出网页性能数据

FCP首屏:domContentLoadedEventEnd/Start - fetchStart

FP白屏:domInteractive - fetchStart

使用performance.getEntries()获取所有资源请求的时间数据

使用performance.getEntriesByName(name)获取特定名称的时间数据

FCP = performance.getEntriesByName("first-contentful-paint")[0].startTime - navigationStart

FP:item.startTime

LCP:创建性能观察器PerformanceObserver

使用performance.now()精确计算程序执行时间

使用performance.mark以及performance.measure手动测量性能

Google performance 面板

浏览器进程:多进程

主进程:显示、交互,增删进程

Browser Process

主进程是浏览器的核心,负责管理用户界面、显示内容、用户交互等。

它还负责创建和销毁其他进程,如渲染进程、插件进程等。

UI进程:控制地址栏、书签、前进后退

存储进程:cookie,webstorage,indexDB

渲染进程:每个标签页或窗口都有一个独立的渲染进程,解析HTML,执行js

js引擎和页面渲染引擎是在同一个渲染线程之内,两者是互斥关系。

Renderer Process

每个标签页或窗口都有一个独立的渲染进程。

渲染进程负责解析HTML、执行JavaScript、渲染页面内容,同时拥有自己的渲染引擎和JavaScript引擎。

这种隔离性可以防止一个页面的崩溃影响其他页面。

插件进程

Plugin Process

如果页面使用了插件(如Flash、PDF阅读器等),浏览器会为插件创建独立的进程,以增加安全性和稳定性。

GPU进程:图像渲染

一些浏览器使用独立的GPU进程来处理图形渲染,以提高性能并减少主渲染进程的工作量。

网络进程:请求

一些浏览器还将网络请求和资源下载放在单独的进程中,以便更好地管理网络连接。

LightHouse:性能分析工具(v8/v9性能指标)

Lighthouse是由Google开发的一款开源工具,用于评估Web应用程序的性能、可访问性、最佳实践和SEO(搜索引擎优化)等方面的质量。Lighthouse可以作为一个独立的CLI(命令行界面)工具,也可以通过Chrome浏览器的开发者工具来运行。

Opportunities优化建议列表

Preload key requests首页资源 preload 预加载
Serve images in next-gen formats

使用新的图片格式,比如 webp 相对 png jpg 格式体积更小

Diagnostics 诊断问题列表

A long cache lifetime can speed up repeat visits to your page这些资源需要提供长的缓存期,现发现图片都是用的协商缓存,显然不合理

Image elements do not have explicit width and height给图片设置具体的宽高,减少 cls 的值

FCP首次内容绘制(First Contentful Paint)⭐

标准≤2s

FCP衡量的是,在用户导航到页面后,浏览器呈现第一块DOM内容所需的时间。

页面上的图片非白色<canvas>元素svg都被认为是DOM内容;

iframe内的任何内容都不包括在内

<iframe>(内联框架)是HTML中的一个标签,用于在当前网页中嵌入另一个网页或资源。这可以用于在页面中显示其他网站的内容,或者将不同的Web内容集成到一个页面中

<!DOCTYPE html>
<html>
<head>
    <title>嵌入Google搜索</title>
</head>
<body>
    <h1>在页面中嵌入Google搜索</h1>
    
    <iframe src="https://www.google.com" width="800" height="600" frameborder="0"></iframe>
    
    <p>这是一个嵌入了Google搜索的示例。</p>
</body>
</html>

优化手段:缩短字体加载时间

LCP最大内容绘制(Largest Contentful Paint)⭐

标准≤2.5 秒

LCP测量视口最大的内容元素何时呈现到屏幕上。这接近于用户可以看到页面的主要内容

LCP 的数据会通过 PerformanceEntry 对象记录, 每次出现更大的内容渲染, 则会产生一个新的 PerformanceEntry 对象

原因

缓慢的服务器响应速度
阻塞渲染的 JavaScript 和 CSS
缓慢的资源加载速度
客户端渲染

首次像素绘制 FP(First Paint)白屏⭐

从输入 url 开始:dns 、tcp 、http请求、返回 html 文档、html 文档解析

标准≤2s

从页面开始加载到浏览器中检测到渲染(任何渲染)时被触发(例如背景改变,样式应用等)

CLS(Cumulative Layout Shift):累积布局偏移,(衡量网页元件视觉稳定性)⭐

标准≤0.1

累积布局偏移 (CLS) 是测量视觉稳定性的一个以用户为中心的重要指标

CLS 较差的最常见原因为:无尺寸、动态注入

1.无尺寸的图像

2.无尺寸的嵌入和 iframe

3.动态注入的内容

优化手段

1. 除非是对用户交互做出响应,否则切勿在现有内容的上方插入内容
2. 倾向于选择transform动画

TTI(Time to Interactive):变成完全交互式的时间

TTI测量一个页面变成完全交互式需要多长时间

当页面显示

有用的内容(由First Contentful Paint衡量),

为大多数可见的页面元素注册了事件处理程序

并且页面在50毫秒内响应用户交互时,

页面被认为是完全交互式的。

TBT(Total Blocking Time):阻止响应时间

长时间任务(Long Tasks): 长时间任务是指在浏览器主线程上执行的任务,其持续时间超过50毫秒(通常)

后果:这可能会阻塞其他任务的执行,包括用户输入响应,JavaScript脚本的执行、DOM操作、CSS计算等。

它衡量了在页面加载过程中由于长时间任务(Long Tasks)的存在而导致的用户交互延迟。TBT总和是一个网页加载期间所有长时间任务阻塞部分之和。

例如,如果检测到一个 70 毫秒长的任务,则阻塞部分将为 20 毫秒

它将这些长时间任务的阻塞部分的持续时间相加,以获得用户可能面临的总延迟。这包括了从FCPTTI之间的时间段内的所有长时间任务,因为这些任务可能会影响用户对页面的响应速度,从而影响了用户体验。

通过监测和最小化TBT总和,开发人员可以努力提高网页的性能,以确保用户能够更快地与页面进行互动,减少潜在的交互延迟。

SI(Speed Index):帧之间的视觉进展

SI指数衡量内容在页面加载期间视觉显示的速度。Lighthouse首先在浏览器中捕获页面加载的视频,并计算帧之间的视觉进展

优化手段:减少主线程工作 、JavaScript的执行时间

首字节时间:网络后端的整体响应耗时

主文档返回第一个字节的时间,是页面加载性能比较重要的指标。对用户来说一般无感知,对于开发者来说,则代表访问网络后端的整体响应耗时。

window.performance API

性能 API 提供了许多与网页性能和资源加载有关的信息,这些信息以性能条目(Performance Entries)的形式存在。这些性能条目包括导航性能(如页面加载时间)、资源加载性能(如图像、脚本和样式表加载时间)

// 获取所有资源加载性能条目
const resourceEntries = performance.getEntriesByType('resource');

// 遍历资源性能条目并打印
resourceEntries.forEach((entry) => {
    console.log('资源类型:', entry.initiatorType);
    console.log('资源 URL:', entry.name);
    console.log('加载时间:', entry.duration);
});

从性能API中获取"paint"类型的性能条目,然后查找并处理名称为'first-contentful-paint'的条目,将其描述为'FCP'并将开始时间转换为整数后添加到事务的页面上下文中。

// 获取性能信息并筛选出类型为 'paint' 的条目
window.performance
    .getEntries()
    .filter((entry: Record<string, any>) => {
        return entry.entryType === 'paint';
    })
    .forEach((item: Record<string, any>) => {
        // 如果条目的名称是 'first-contentful-paint',则执行以下操作
        if (item.name === 'first-contentful-paint') {
            // 将信息添加到事务的页面上下文中
            transaction.addPageContext({
                description: 'FCP', // 描述为 'FCP'
                time: floatToInt(item.startTime) // 将开始时间转换为整数并添加到 'time' 属性
            });
        }
    });

Performance 是一个浏览器全局对象,提供了一组 API 用于编程式地获取程序在某些节点的性能数据。它包含一组高精度时间定义,以及配套的相关方法。我们可以直接在浏览器控制台打印window.performance 

// 获取 performance 数据
var performance = {
    // memory 是非标准属性,只在 Chrome 有
    // 我有多少内存
    memory: {
        usedJSHeapSize:  16100000, // JS 对象(包括V8引擎内部对象)占用的内存,一定小于 totalJSHeapSize
        totalJSHeapSize: 35100000, // 可使用的内存
        jsHeapSizeLimit: 793000000 // 内存大小限制
    },

    // 我从哪里来?
    navigation: {
        redirectCount: 0, // 如果有重定向的话,页面通过几次重定向跳转而来
        type: 0           // 0   即 TYPE_NAVIGATENEXT 正常进入的页面(非刷新、非重定向等)
                          // 1   即 TYPE_RELOAD       通过 window.location.reload() 刷新的页面
                          // 2   即 TYPE_BACK_FORWARD 通过浏览器的前进后退按钮进入的页面(历史记录)
                          // 255 即 TYPE_UNDEFINED    非以上方式进入的页面
    },
//  核心时间相关
    timing: {
        // 在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload 的时间戳,如果无前一个网页 unload ,则与 fetchStart 值相等
        navigationStart: 1441112691935,

        // 前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0
        unloadEventStart: 0,

        // 和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳
        unloadEventEnd: 0,

        // 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0
        redirectStart: 0,

        // 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0
        redirectEnd: 0,

        // 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
        fetchStart: 1441112692155,

        // DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
        domainLookupStart: 1441112692155,

        // DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
        domainLookupEnd: 1441112692155,

        // HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等
        // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间
        connectStart: 1441112692155,

        // HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等
        // 注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间
        // 注意这里握手结束,包括安全连接建立完成、SOCKS 授权通过
        connectEnd: 1441112692155,

        // HTTPS 连接开始的时间,如果不是安全连接,则值为 0
        secureConnectionStart: 0,

        // HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存
        // 连接错误重连时,这里显示的也是新建立连接的时间
        requestStart: 1441112692158,

        // HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
        responseStart: 1441112692686,

        // HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
        responseEnd: 1441112692687,

        // 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件
        domLoading: 1441112692690,

        // 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件
        // 注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源
        domInteractive: 1441112693093,

        // DOM 解析完成后,网页内资源加载开始的时间
        // 在 DOMContentLoaded 事件抛出前发生
        domContentLoadedEventStart: 1441112693093,

        // DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)
        domContentLoadedEventEnd: 1441112693101,

        // DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件
        domComplete: 1441112693214,

        // load 事件发送给文档,也即 load 回调函数开始执行的时间
        // 注意如果没有绑定 load 事件,值为 0
        loadEventStart: 1441112693214,

        // load 事件的回调函数执行完毕的时间
        loadEventEnd: 1441112693215

        // 按照字母排序
        // connectEnd: 1441112692155,
        // connectStart: 1441112692155,
        // domComplete: 1441112693214,
        // domContentLoadedEventEnd: 1441112693101,
        // domContentLoadedEventStart: 1441112693093,
        // domInteractive: 1441112693093,
        // domLoading: 1441112692690,
        // domainLookupEnd: 1441112692155,
        // domainLookupStart: 1441112692155,
        // fetchStart: 1441112692155,
        // loadEventEnd: 1441112693215,
        // loadEventStart: 1441112693214,
        // navigationStart: 1441112691935,
        // redirectEnd: 0,
        // redirectStart: 0,
        // requestStart: 1441112692158,
        // responseEnd: 1441112692687,
        // responseStart: 1441112692686,
        // secureConnectionStart: 0,
        // unloadEventEnd: 0,
        // unloadEventStart: 0
    }
}

性能统计

Level 1 的规范(window.performance.timing)

  • performance.timing 接口(定义了从 navigationStart 至 loadEventEnd 的 21 个只读属性)
  • performance.navigation(定义了当前文档的导航信息,比如是重载还是向前向后等)

v1.jpeg

从当前浏览器窗口卸载旧页面开始,到新页面加载完成,整个过程一共被切分为 9 个小块:提示卸载旧文档、重定向/卸载、应用缓存、DNS 解析、TCP 握手、HTTP 请求处理、HTTP 响应处理、DOM 处理、文档装载完成。每个小块的首尾、中间做事件分界,取 Unix 时间戳,两两事件之间计算时间差,从而获取中间过程的耗时(精确到毫秒级别)。

v3.jpeg

level2规范(performance.getEntriesByType('navigation')[0])

v2.jpeg

确定统计起始点

页面性能统计的起始点时间,应该是用户输入网址回车后开始等待的时间

fetchStart:准备好使用 HTTP 请求获取文档

浏览器重定向、卸载页面的耗时对页面加载分析并无太大作用;通常使用 fetchStart 作为统计起始点。

性能数据计算公式

使用 performance.timing 简单计算出网页性能数据

FCP首屏:domContentLoadedEventEnd/Start - fetchStart

具备一定意义上的指标可以使用, domContentLoadedEventEnd - fetchStart,甚至使用loadEventStart - fetchStart,此时页面DOM树已经解析完成并且显示内容。

页面完全加载(首次渲染时间+DOM解析耗时+同步JS执行+资源加载耗时):

data['loadEventStart'] - data['fetchStart']

FP白屏:domInteractive - fetchStart

此时页面开始解析DOM树,页面渲染的第一个元素也会很快出现。

  • 重定向耗时:redirectEnd - redirectStart

  • DNS 查询耗时:domainLookupEnd - domainLookupStart

  • TCP 链接耗时:connectEnd - connectStart

  • HTTP 请求耗时:responseEnd - responseStart

  • 解析 dom 树耗时:domComplete - domInteractive

  • DOM ready 时间:domContentLoadedEventEnd - navigationStart

 HTML 加载完成时间, 即 DOM Ready 时间

页面完全加载:首次渲染时间 + DOM 解析耗时 + 同步 JS 执行 + 资源加载耗时

//性能数据调用的api
data = window.performance.getEntriesByType('navigation')
//若上述api不支持则使用(将废弃)
data = window.performance.timing
  • onload:loadEventEnd - navigationStart

使用performance.getEntries()获取所有资源请求的时间数据

let times = {};
let t = window.performance.timing;

// 优先使用 navigation v2  https://www.w3.org/TR/navigation-timing-2/
if (typeof win.PerformanceNavigationTiming === 'function') {
  try {
    var nt2Timing = performance.getEntriesByType('navigation')[0]
    if (nt2Timing) {
      t = nt2Timing
    }
  } catch (err) {
  }
}

//重定向时间
times.redirectTime = t.redirectEnd - t.redirectStart;

//dns查询耗时
times.dnsTime = t.domainLookupEnd - t.domainLookupStart;

//TTFB 读取页面第一个字节的时间
times.ttfbTime = t.responseStart - t.navigationStart;

//DNS 缓存时间
times.appcacheTime = t.domainLookupStart - t.fetchStart;

//卸载页面的时间
times.unloadTime = t.unloadEventEnd - t.unloadEventStart;

//tcp连接耗时
times.tcpTime = t.connectEnd - t.connectStart;

//request请求耗时
times.reqTime = t.responseEnd - t.responseStart;

//解析dom树耗时
times.analysisTime = t.domComplete - t.domInteractive;

//白屏时间 
times.blankTime = (t.domInteractive || t.domLoading) - t.fetchStart;

//domReadyTime
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;

获取所有资源请求的时间数据,这个函数返回一个按 startTime 排序的对象数组

我们直接面板输出一下。

11.png

使用performance.getEntriesByName(name)获取特定名称的时间数据

FCP = performance.getEntriesByName("first-contentful-paint")[0].startTime - navigationStart

FP:item.startTime

window.performance
    .getEntries()
    .filter((entry: Record<string, any>) => {
      return entry.entryType === 'paint'
    }).forEach((item: Record<string, any>) => {
      if (item.name === 'first-paint') {
        transaction.addPageContext({
          description: 'FP',
          time: floatToInt(item.startTime)
        })
      } 
    })

LCP:创建性能观察器PerformanceObserver

// 创建性能观察器
const observer = new PerformanceObserver((entryList) => {
    // 从观察到的条目中提取性能条目
    const entries = list.getEntries();
    // 获取最后一个性能条目
    const lastEntry = perfEntries[perfEntries.length - 1];
    // 从最后一个性能条目中提取最大内容渲染时间 (LCP)
    const lcp = lastEntry.renderTime || lastEntry.loadTime;
    // 打印最大内容渲染时间 (LCP)
    console.log('LCP:', lcp);
});

// 开始观察指定类型的性能条目(最大内容渲染)
observer.observe({ entryTypes: ['largest-contentful-paint'] });

使用performance.now()精确计算程序执行时间

performance.now方法返回当前网页自从performance.timing.navigationStart到当前时间之间的微秒数(毫秒的千分之一)。也就是说,它的精度可以达到 100 万分之一秒。

那么我们可以通过两次调用 最后计算出 js 某种操作的精确耗时

const start = performance.now();
doTasks(); // 这里是耗时操作
const end = performance.now();
console.log("耗时:" + (end - start) + "微秒。");

使用performance.mark以及performance.measure手动测量性能

这块具体的代码示例 建议大家可以直接访问这里去查看

咱们如果想自定义搜集性能数据指标 做前端的性能监控系统 那么这两个 api 是非常给力的

Google performance 面板

let times = {};
let t = window.performance.timing;

// 优先使用 navigation v2  https://www.w3.org/TR/navigation-timing-2/
if (typeof win.PerformanceNavigationTiming === 'function') {
  try {
    var nt2Timing = performance.getEntriesByType('navigation')[0]
    if (nt2Timing) {
      t = nt2Timing
    }
  } catch (err) {
  }
}

//重定向时间
times.redirectTime = t.redirectEnd - t.redirectStart;

//dns查询耗时
times.dnsTime = t.domainLookupEnd - t.domainLookupStart;

//TTFB 读取页面第一个字节的时间(TTFB有多种计算方式,相减的参数可以是 requestStart 或者 startTime)
times.ttfbTime = t.responseStart - t.requestStart;

//DNS 缓存时间
times.appcacheTime = t.domainLookupStart - t.fetchStart;

//卸载页面的时间
times.unloadTime = t.unloadEventEnd - t.unloadEventStart;

//tcp连接耗时
times.tcpTime = t.connectEnd - t.connectStart;

//(Trans)内容传输耗时
times.transTime = t.responseEnd - t.responseStart;

//解析dom树耗时
times.analysisTime = t.domComplete - t.domInteractive;

//白屏时间 
times.blankTime = (t.domInteractive || t.domLoading) - t.fetchStart;

//domReadyTime
times.domReadyTime = t.domContentLoadedEventEnd - t.fetchStart;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值