性能调优--gzip、缓存、content-download、逐针渲染、Queueing、动态延迟加载、最小化主线程工作
本文主要讲述,关于 Chrome Content Download 时间过长问题调查经过,及相关优化方案
chunk-136cc8c0.js
是上图地图 geojson,587 kB 用了 1.01s,作为系统首页,会导致中间地图(视觉中心)出现长时间的空白,对于用户体验来说,极其不友好。
怀疑一:是不是网络环境不好导致?
在开发环境下运行(本地)也会出现类似情况,且更重要的是 chunk-7182b1fa.js
933kB 才用了 35ms。因此可以排除网络坏境导致。
怀疑二:缓存导致?
某些 chunk 请求用时短,某些请求用时长;是不是缓存起的作用。
- 缓存(304)的确可以加快资源的请求
- 但对于
chunk-136cc8c0.js
和其他请求依然不是一个量级的
怀疑三:浏览器并行加载个数有限,导致排队时间过长?
Chrome 浏览器默认并行加载个数为 6 个,过多的请求的确会引起资源请求排队。
通过 Chrome => Network => Timing 查看:
Queueing(排队): 浏览器会在以下情况下对请求进行队列处理:
- 有更高优先级的请求。(浏览器 Network 中可以通过 Priority 查看)
- 已经建立了 6 个 TCP 连接(HTTP/1.0和HTTP/1.1协议下的限制)
- The browser is briefly allocating space in the disk cache
Stalled(阻塞): 请求可能会因为 Queueing 中描述的任何原因而停止
Request sent(发送请求): 发送HTTP请求的时间(从第一个bit到最后一个bit)
Waiting (TTFB)(等待响应): 浏览器正在等待响应的第一个字节。TTFB表示时间到第一个字节。这个时间包括1个延迟往返和服务器准备响应所花费的时间
Content Download(下载): 下载HTTP响应的时间(包含头部和响应体)
整体 Queueing(排队)并没有消耗多少时间(1.28ms),而是 Content Download 消耗了大量时间(1.01s)。所以断定并不是排队时间过长导致该问题。
更详细的,可以查看 Chrome 开发文档:这里
怀疑四:Cpu 被耗尽,浏览器”停顿“?
查了相关的帖子,这篇 最后的回答「Frontend app is doing too much work」给了另一个方向。
是不是初始阶段进行大量的 JS 工作,导致 cpu 被耗尽了,使得浏览器处于了”停顿“状态。
通过 Chrome => Performance => Start recording:
chunk-136cc8c0.js
加载前后 cpu 使用率为 100%,导致资源请求和后续等待执行的时间都很长。初步断定,和 cpu 占用率用很大关系。
问题有了方向,后续就是针对问题出各种优化方案
优化方式
通用:开启缓存
Nginx 开启静态资源(css、js)缓存配置:
在 server 中的 location / 的配置中增加如下配置
location / {if ($request_filename ~* ^.*?\.(js|css)$){# 缓存时效性可以根据项目诉求,自行设定expires 30d;}root xxx/dist;index index.html;....
}
通用:开启 Gzip
对静态资源进行 gzip,能起到巨大的效果(实测:40M的内容,gzip完不足10M)。
第1步:按照依赖
$ npm install compression-webpack-plugin --save-dev
第2步:vue.config.js
开启 gzip 压缩
const CompressionPlugin = require("compression-webpack-plugin");module.exports = {plugins: [new CompressionPlugin()],
};
详细配置可查看 compression-webpack-plugin
第3步:在 Nginx 配置文件中的 http 或者 server 中增加配置
server {gzip on;gzip_vary on;gzip_types application/javascript text/css;location / {...}
}
由于是 geojson,压缩空间有限但也减少了一半,对于 http 请求速度会有很大的提高(对于纯 css、js代码,效果会更加明显)。
可选:动态延迟加载
页面中存在好多 Dialog 等下钻需要的组件,可以通过 webpack import()
动态加载,避免进入页面全部发起请求。
import()
可以动态的加载模块。调用 import
的之处,被视为分割点,被请求的模块和它引用的所有子模块,会分割到一个单独的 chunk 中。
原形式:
import detailEventDialog from './components/detail-event.vue'
import detailVulnDialog from './components/detail-vuln.vue'
import detailCompDialog from './components/detail-comp.vue'
import detailWeakDialog from './components/detail-weak.vue'
import detailWeakTabDialog from './components/detail-weak-tab.vue'
import detailAssetDialog from './components/detail-asset.vue'
import detailUserDialog from './components/detail-user.vue'export default {components: {detailEventDialog, detailVulnDialog,detailCompDialog,detailWeakDialog,detailWeakTabDialog,detailAssetDialog,detailUserDialog}
}
修改后:
export default {components: {detailEventDialog: () => import('./components/detail-event.vue'),detailVulnDialog: () => import('./components/detail-vuln.vue'),detailCompDialog: () => import('./components/detail-comp.vue'),detailWeakDialog: () => import('./components/detail-weak.vue'),detailWeakTabDialog: () => import('./components/detail-weak-tab.vue'),detailAssetDialog: () => import('./components/detail-asset.vue'),detailUserDialog: () => import('./components/detail-user.vue')}
}
import()
必须至少包含一些关于模块的路径信息。打包可以限定于一个特定的目录或文件集,以便于在使用动态表达式时 - 包括可能在 import()
调用中请求的每个模块。例如, import(./locale/${language}.json)
会把 .locale
目录中的每个 .json
文件打包到新的 chunk 中。在运行时,计算完变量 language
后,就可以使用像 english.json
或 german.json
的任何文件。 – webpack import
可选:DOM逐针渲染
vue mixins
export default function (maxCount = 0) {return {data () {return {// 展示权重,默认为0displayPriority: 0,running: true}},mounted () {this._startLoop()},methods: {_startLoop () {// 最大渲染数为0时,停止助阵逐帧渲染if (maxCount === 0) returnthis.running = trueconst step = () => {this.displayPriority++if (this.running && this.displayPriority <= maxCount) {requestAnimationFrame(step)}}requestAnimationFrame(step)},_stopLoop () {this.running = false},delayRender (priority) {return this.displayPriority >= priority}},activated () {// 激活状态开始渲染!this.running && this._startLoop()},deactivated () {// 停止渲染监听this._stopLoop()},beforeDestroy () {// 停止渲染监听this._stopLoop()}}
}
使用
<template><div><el-row>...</el-row><el-row v-if="delayRender(3)">...</el-row><el-row v-if="delayRender(6)">...</el-row><el-row v-if="delayRender(9)">...</el-row></div>
</template>
<script>export default {mixins: [delayRenderService(9)]}
</script>
针对业务代码瘦身
针对特定业务需求,对静态资源进行了瘦身(删除了一些无用的第三方、自研组件、及静态资源的引用);然后将 chunk-136cc8c0.js
(geojson) 加载时机提前,获取到资源后,先行渲染底图。
最小化主线程工作
浏览器的渲染器进程将代码转换为用户可以与之交互的网页。默认情况下,渲染器进程的主线程通常处理大部分代码:它解析 HTML 并构建 DOM,解析 CSS 并应用指定的样式,以及解析、评估和执行 JavaScript。主线程还处理用户事件。因此,每当主线程忙于做其他事情时,网页可能无法响应用户交互,从而导致糟糕的体验。
方式 | |
---|---|
Script evaluation |
优化第三方 JavaScript 去抖动输入处理程序 使用网络工作者 |
Style and layout |
减少样式计算的范围和复杂性 避免大型、复杂的布局和布局颠簸 |
Rendering |
坚持只使用合成器的属性并管理层数 简化油漆复杂性并减少油漆区域 |
Parsing HTML and CSS |
提取关键 CSS 缩小 CSS 推迟非关键 CSS |
Script parsing and compilation |
通过代码拆分减少 JavaScript 负载 删除未使用的代码 |
Garbage collection | 使用以下命令监控网页的总内存使用情况 measureMemory() |
最终效果
性能调优--gzip、缓存、content-download、逐针渲染、Queueing、动态延迟加载、最小化主线程工作相关推荐
- Redis基础用法、高级特性与性能调优以及缓存穿透等分析
目录 一.Redis介绍 二.Redis数据结构及常用的命令 三.Redis持久化策略选择 四.内存管理与数据淘汰机制 五.Redis过期策略及实现原理 1 说明 2 设置过期时间 3 三种过期 ...
- SPDK RBD bdev性能调优
前言 在前文[1]中,我们简述了SPDK中RBD bdev模块以及所依赖的librbd接口的调用方法.本文就SPDK RBD bdev结合Ceph RBD的使用进行更为深入的探讨,并结合实际的应 ...
- Ceph分布式存储(架构 配置与使用 原理 性能调优)
Ceph分布式存储 Ceph分布式存储 1. Ceph概述 1.1 背景 1.2 介绍 1.3 特点 1.4 分布式存储系统横纵对比 2. Ceph架构设计 2.1 Ceph整体设计 2.2 逻辑架构 ...
- iOS应用性能调优的25个建议和技巧【转】
转载自:http://blog.jobbole.com/37984/ 首页 最新文章 资讯 程序员 设计 IT技术 创业 在国外 营销 趣文 特别分享 更多 > - Navigation - 首 ...
- 程序员精进之路:性能调优利器--火焰图
作者:厉辉,腾讯 CSIG 后台开发工程师 本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一 ...
- 参数调优为什么要采样_程序员精进之路:性能调优利器--火焰图
本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一下,曾经作为编程新手的我们是如何调优程序的? ...
- iOS应用性能调优建议
本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/,你还可以 ...
- iOS应用性能调优的25个建议和技巧
写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/ ...
- 编程新手该如何调优程序?程序员必备性能调优利器——火焰图
本文主要分享火焰图使用技巧,介绍 systemtap 的原理机制,如何使用火焰图快速定位性能问题原因,同时加深对 systemtap 的理解. 让我们回想一下,曾经作为编程新手的我们是如何调优程序的? ...
最新文章
- tc溜溜865手机投屏卡_游戏物理外挂再升级!腾讯黑鲨游戏手机3S开箱体验
- 简单的了解一下AQS吧
- trinitycore MySQL模块_Windows下编译TrinityCore服务端
- C#LeetCode刷题-脑筋急转弯
- oracle全角括号忽略,Oracle中SQL查询语句日文不区分全角/半角
- editplus java acp_EditPlus配置Java编译器
- 时域分析——有量纲特征值含义一网打尽
- 基于图像识别的火灾探测技术
- LeetCode_回文数(三种解法-Java)
- Parcel 中文文档 | Parcel 中文网
- HackTheBox - Unified
- (一)Redis——五大数据类型及基础知识
- 大一学生《Web编程基础》期末网页制作 HTML+CSS+JavaScript 企业网页设计实例
- hangye5:2345导航将出嫁史玉柱 网址站出路大盘点
- 云端服务器维护,云端服务器维护
- Json完整版介绍和工具类解析应用
- 单相逆变器及基于STM32 SPWM生成代码
- js中如何判断是否是数组?
- java 工厂模式实现_Java三种实现工厂模式的方法
- 网络字节顺序 大头小头问题
热门文章
- 老师教我们用计算机画画就是彩虹,一年级上课文
- JAVA学习笔记五---函数
- mysql 5.7版本异常Expression #1 of ORDER BY clause is not in GROUP BY clause and contains 处理
- [MOOC]物联网技术笔记-2.物联网的概念和特征
- 备份谷歌或其他浏览器插件
- 十大算法--支持向量机
- 2019蓝桥杯国赛总结
- 微信小程序|使用小程序制作一个足球拼图小游戏
- OaisimWithS1搭建笔记(2019.5)
- 飞桨day-04 NLP实践作业