mysql视频教程推荐,性能优化之关于像素管道及优化

Posted 程序员超时空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql视频教程推荐,性能优化之关于像素管道及优化相关的知识,希望对你有一定的参考价值。

JS/CSS(代码变动)


我们使用 JS 来改变样式是最为常见的,对于通过 JS 来改变动画,有以下几点需要注意:

  • 动画效果尽量使用 requestAnimationFrame 而不是使用 setTimeout 或者 setInterval

  • 由于 JS 是单线程运行,请将需要耗费大量时间运行的任务放到 Web Worker 进行执行。

  • 请使用微任务来进行 DOM 更改,如果你不了解什么是微任务,请点击这里

  • 使用 Chrome DevTools 的 Timeline 和 javascript 分析器来评估 JavaScript 的影响

使用requestAnimationFrame

大多时候,我想大部分人执行一个动画效果都会用到 setTimeout 或者 setInterval 这两个函数,但是这两个函数和requestAnimationFrame 有什么区别呢,似乎用下来感觉差不多?

这要从屏幕刷新率说起。

屏幕刷新频率

屏幕刷新频率,即图像在屏幕上更新的速度,也即屏幕上的图像每秒钟出现的次数,它的单位是赫兹(Hz)。 对于一般笔记本电脑,这个频率大概是60Hz。

因此,当你对着电脑屏幕什么也不做的情况下,显示器也会以每秒60次的频率正在不断的更新屏幕上的图像。为什么你感觉不到这个变化? 那是因为人的眼睛有视觉停留效应,即前一副画面留在大脑的印象还没消失,紧接着后一副画面就跟上来了,这中间只间隔了16.7ms(1000/60≈16.7), 所以会让你误以为屏幕上的图像是静止不动的。而屏幕给你的这种感觉是对的,试想一下,如果刷新频率变成1次/秒,屏幕上的图像就会出现严重的闪烁,这样就很容易引起眼睛疲劳、酸痛和头晕目眩等症状。

动画原理

根据上面的原理我们知道,你眼前所看到图像正在以每秒60次的频率刷新,由于刷新频率很高,因此你感觉不到它在刷新。而动画本质就是要让人眼看到图像被刷新而引起变化的视觉效果,这个变化要以连贯的、平滑的方式进行过渡。 那怎么样才能做到这种效果呢?

刷新频率为60Hz的屏幕每16.7ms刷新一次,我们在屏幕每次刷新前,将图像的位置向左移动一个像素,即1px。这样一来,屏幕每次刷出来的图像位置都比前一个要差1px,因此你会看到图像在移动;由于我们人眼的视觉停留效应,当前位置的图像停留在大脑的印象还没消失,紧接着图像又被移到了下一个位置,因此你才会看到图像在流畅的移动,这就是视觉效果上形成的动画。

setTimeoutsetInterval

理解了上面的概念以后,我们不难发现,setTimeout 其实就是通过设置一个间隔时间来不断的改变图像的位置,从而达到动画效果的。但我们会发现,利用seTimeout实现的动画在某些配置较低的机器上会出现卡顿、抖动的现象。 这种现象的产生有两个原因:

  • setTimeout的执行时间并不是确定的。在Javascript中, setTimeout 任务被放进了异步队列中,只有当主线程上的任务执行完以后,才会去检查该队列里的任务是否需要开始执行,因此 setTimeout 的实际执行时间一般要比其设定的时间晚一些。

  • 刷新频率受屏幕分辨率和屏幕尺寸的影响,因此不同设备的屏幕刷新频率可能会不同,而 setTimeout 只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。

以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致,从而引起丢帧现象。 那为什么步调不一致就会引起丢帧呢?

  • 第0ms: 屏幕未刷新,等待中,setTimeout也未执行,等待中;

  • 第10ms: 屏幕未刷新,等待中,setTimeout开始执行并设置图像属性left=1px;

  • 第16.7ms: 屏幕开始刷新,屏幕上的图像向左移动了1px, setTimeout 未执行,继续等待中;

  • 第20ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=2px;

  • 第30ms: 屏幕未刷新,等待中,setTimeout开始执行并设置left=3px;

  • 第33.4ms:屏幕开始刷新,屏幕上的图像向左移动了3px, setTimeout未执行,继续等待中;

从上面的绘制过程中可以看出,屏幕没有更新left=2px的那一帧画面,图像直接从1px的位置跳到了3px的的位置,这就是丢帧现象,这种现象就会引起动画卡顿。

requestAnimationFrame

setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

除此之外,requestAnimationFrame还有以下两个优势:

  • CPU节能:使用setTimeout实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而requestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。

  • 函数节流:在高频率事件(resize,scroll等)中,为了防止在一个刷新间隔内发生多次函数执行,使用requestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每16.7ms刷新一次,多次绘制并不会在屏幕上体现出来。

Web Worker

由于 JavaScript 是单线程的,遇到大量计算问题会使整个页面卡住,造成页面十分卡顿的感觉,在许多情况下,可以将纯计算工作移到 Web Worker,例如,如果它不需要 DOM 访问权限。数据操作或遍历(例如排序或搜索)往往很适合这种模型,加载和模型生成也是如此。

但是,由于 Web Worker 不能访问 DOM,如果您的工作必须在主线程上执行,请考虑一种批量方法,将大型任务分割为微任务,每个微任务所占时间不超过几毫秒,并且在每帧的 requestAnimationFrame 处理程序内运行,并且,您将需要使用进度或活动指示器来确保用户知道任务正在被处理,从而有助于主线程始终对用户交互作出快速响应。

避免微优化 JavaScript

我知道许多人对优化有着极致的追求,可能一个函数比另外一个函数快上 10 倍,比如请求元素的 offsetTop 比计算 getBoundingClientRect() 要快,但是,每帧调用这类函数的次数几乎总是很少,一般只能节省零点几毫秒的时间。

当然我并不是说这样做不好,但是这花费的精力和获得的提升相比起来很不值得,也就是说,花费了大力气修改,可能界面毫无变化,还会破坏代码的结构性,我建议,代码结构性和稳定性的重要性远远大于微优化。

Style(样式计算)


大家都清楚重排和重绘这两个词,改变 DOM 结构就会导致浏览器重新计算元素样式,在很多情况下还会对整个页面或页面的一部分进行布局(即自动重排)。这就是所谓的样式的计算。

计算样式实际上分为两个步骤:

  1. 创建一组匹配选择器(浏览器计算出给指定元素应用哪些类、伪选择器和 ID)

  2. 从匹配选择器中获取所有样式规则,并计算出此元素的最终样式

用于计算某元素计算样式的时间中大约有 50% 用来匹配选择器,而另一半时间用于从匹配的规则中构建

这一节其实没什么好写的,其实就两点需要注意一下:

  • 降低选择器的复杂性

  • 减少必须计算其样式的元素数量

降低选择器的复杂性

例如:


.box:nth-last-child(-n+1) .title {

  /* styles */

}

这个 class ,浏览器会查找这是否为有 title 类的元素,其父元素恰好是负第 N 个子元素加上 1 个带 box 类的元素?

计算此结果可能需要大量时间,具体取决于所用的选择器和相应的浏览器。

改为这样可能会更好:


.final-box-title {

  /* styles */

}

当然,有些样式必不可免会使用到第一种写法,但是我建议,尽量少用这种写法。

举个具体的栗子:

这是页面上的元素:


<div class="box"></div>

<div class="box"></div>

<div class="box b-3"></div>

这是写的 css 选择器


.box:nth-child(3)

.box .b-3

查找的元素越多,查找的花费时间越多。

如果 .box:nth-child(3) 花费时间是 2ms, .box .b-3 花费时间是 1ms,如果有 100 个元素,.box:nth-child(3) 花费 200ms,.box .b-3 花费 100ms,时间差距就出来了。

总体来说,计算元素的计算样式的最糟糕的开销情况是元素数量乘以选择器数量,因为需要对照每个样式对每个元素都检查至少一次,看它是否匹配。

所以请尽量减少无效的 class,可能写在页面上不会造成任何影响,但是这会给浏览器造成负担,所以我建议使用 BEM 命名规范。

建议使用 BEM

BEM(块、元素、修饰符)之类的编码方法实际上纳入了上述选择器匹配的性能优势,因为它建议所有元素都有单个类,并且在需要层次结构时也纳入了类的名称:


.list { }

.list__list-item { }

如果需要一些修饰符,像在上面我们想为最后一个子元素做一些特别的东西,就可以按如下方式添加:


.list__list-item--last-child {}

用 sass 则可以更好的组织 BEM


.list {

  &__list-item {

    &--last-child {}

  }

}

Layout(布局)


布局的过程是上就是重排的过程,重排几乎将整个页面重新计算布局,开销之大显而易见。

DOM 的数量以及复杂性将影响到性能。

以下几点建议可以让我们优化布局:

  • 尽可能避免布局操作

  • 使用 flexbox 而不是浮动布局

  • 避免强制同步布局

  • 避免布局抖动

避免强制同步布局

强制同步布局(Forced Synchronous Layout),发生的原因在于在 JavaScript 代码阶段触发了 Layout 部分的 CSS 属性。

例如:读取某个元素的 offsetWidth 值,就会强迫浏览器在此帧就必须更新,浏览器会立即计算样式和布局,然后更新视图,此刻,浏览器会进入读取数据/写入数据的循环中。

用一张图表示:

由于比较抽象,来举个具体的栗子:

栗子 1:


divs.forEach(function(elem, index, arr) {

  if (window.scrollY < 200) {

    element.style.opacity = 0.5;

  }

});

读取 window.scrollY 值会造成 Layout,接着设置透明度,会造成浏览器 读取(读取 scrollY)/ 写入(opacity),forEach 导致浏览器会一直循环进行这种强制同步操作。

修改如下:


const positionY = window.scrollY;



divs.forEach(function(elem, index, arr) {

  if (positionY < 200) {

    element.style.opacity = 0.5;

  }

});

先预读取 scrollY 的值,再进行循环写入操作。

栗子 2:


divs.forEach(function(elem, index, arr) {

  if (elem.offsetHeight < 500) {

    elem.style.maxHeight = '100vh';

  }

});

同上一个问题,读取 offsetHeight,写入 maxHeight

修改如下:


if (elem.offsetHeight < 500) { // 先读取属性值

  divs.forEach(function(elem, index, arr) { // 再更新样式

    elem.style.maxHeight = '100vh';

  });

}

栗子 3:


var newWidth = container.offsetWidth;



divs.forEach(function(elem, index, arr) {

  element.style.width = newWidth;

});

这个栗子是正确的,没问题。

最后

更多Java进阶学习资料、2021大厂面试真题、视频资料可以**点击这里获取到免费下载方式!**

学习视频:

大厂面试真题:

m.offsetHeight < 500) { // 先读取属性值

divs.forEach(function(elem, index, arr) { // 再更新样式

elem.style.maxHeight = '100vh';

});

}




栗子 3:



var newWidth = container.offsetWidth;

divs.forEach(function(elem, index, arr) {

element.style.width = newWidth;

});




这个栗子是正确的,没问题。


# 最后

更多Java进阶学习资料、2021大厂面试真题、视频资料可以**[点击这里获取到免费下载方式!](https://gitee.com/vip204888/java-p7)**

学习视频:

[外链图片转存中...(img-Sv7pNvvN-1628224716140)]

大厂面试真题:

![](https://img-blog.csdnimg.cn/img_convert/d055acbe7d27cdd2721c4a7019fd8180.png)

以上是关于mysql视频教程推荐,性能优化之关于像素管道及优化的主要内容,如果未能解决你的问题,请参考以下文章

Oracle性能优化之性能诊断工具_超越OCP精通Oracle视频教程培训33

Oracle性能优化之性能跟踪工具_超越OCP精通Oracle视频教程培训34

Oracle性能优化之操作系统工具_超越OCP精通Oracle视频教程培训37

Oracle性能优化之统计信息管理_超越OCP精通Oracle视频教程培训32

Oracle性能优化之执行计划管理_超越OCP精通Oracle视频教程培训31

Oracle性能优化之物化视图管理_超越OCP精通Oracle视频教程培训39