新版 Edge (Chromium 内核) 在特定情况下,页面上如果有大量不可见元素时,可能导致神秘卡顿现象的问题成因以及解决办法

前言

从标题看起来,这并不是一个与 Linodas 有关的博文,对吧?

但是,标题说的这个现象,这的确是由修复 Linodas 的一个故障引起的,加之我并没有技术 Blog 一样的东西,想来想去,还是发在 Linodas 的 Blog 上最合适。

这个问题是什么呢?简单来说:

这应该是,小学生套高数公式,然后发现变量为特定数字时,某一型号的计算器型号算出来的结果和其他不一样。

——by 某不愿透露姓名的……

此现象的简要阐述

那么,简单来说就是,在之前的几周,有用户回报在用 Edge 访问 Linodas 的许多页面的时候,都会遇到非常莫名的卡顿现象。

本来以为只是 JS 方面的问题(毕竟我自己不太会前端,JS写得烂也是正常),但经过仔细排查,逐步排查了 JS 问题和页面布局问题之后,发现这个问题并不简单。

具体如何发现故障点就过程就不阐述了(其实很简单,二分法嘛,故障不在这一半,就一定在另一半)。最终发现问题竟然非常简单:

Edge (Chromium 内核版本) 会在页面上读取了一个大型样式表 (CSS文件) 之后。
如果页面上大量元素被设为了不可见
(这包括 类似于 <div hidden> 或 style=’display:none’ 等)时

部分特定的 Edge (经证实与版本号无关) 将会产生巨量卡顿 & 失去响应。
卡顿时间将会随着元素的数量而迅速上升(经过测试大约300个DOM开始出现可体感的卡顿),同时导致CPU占用率飙升,风扇狂响等。

测试页面

以下是一个测试页面,请使用 Edge 访问:https://www.linodas.com/temp/edge_stuck_bug.html

此网页的核心是包含了一个被包裹在

<div hidden></div>

中的巨量(600个)

<div>Edge</div>

对,就是如此简单的结构。(可以自行查看源代码)

当然,除此之外,这个页面还引用了一个 Tailwind CSS 库 的完整版。(必须要引用这个库才能重现此 Bug,但实际上无论用不用到其中的样式,都会触发这个 Bug,这一页面就没有使用其样式)

页面上的JS元素是为了方便视觉察觉而设置的,与此 Bug 无关,可以自行去除。

请注意:此故障在纯本地环境(地址栏是file:///C:/blabla.html  这样的时候)将不会重现,但如果是 本地 Web 环境(如http://localhost/blabla.html)这样的情况,会重现。

请注意,部分 Edge 并不会触发这个 Bug,经过大约30名用户左右的实测,有大约一半用户的 Edge 是完全不会触发这个现象。此故障与版本号无关,截止本文发表日,我的 Edge 版本 102.0.1245.44 会触发此 Bug

目前此故障从未在 Chrome / Firefox / 其他基于 Chromium 的浏览器 / 移动版 Edge 下出现过。

如果你没有遇到卡顿现象,那么可以不看了,如果你遇到了,那么可以继续向下看。

解决办法

很显然,在一个不可见元素里面包含很多元素,这是网页设计中很正常的部分,无论是遮罩,模态窗口,标签页,模拟<select>等,许多网页设计都需要在一个不可见元素中包含很多元素。

因此这个故障几乎是无法避免的。无法解决。

当然,可以有变相解决办法,例如:

1.避免使用不可见元素

简单来说就是用 visibility: hidden; 的方式取代
但是,大家都知道,这个 CSS 会导致元素的占位被表现出来,不是真正的不可见。

2.使用扭曲(脏,Hack)的方式来替换

最简单的办法是使用
position: absolute;visibility: hidden;left:-99999px;

可以完全平替掉
display:none

缺点嘛……这也太丑啦!而且如果有很多东西都涉及这个就会很麻烦。

3.修改页面结构,不使用不可见元素,直接去除,需要用的时候用 Ajax/其他办法 临时加载进来

要改后端代码,愿意改也没问题啦。

4.不用Edge

完美方案!

但是!

经过我询问一个不愿透露姓名的 Microsoft 员工之后,得到了一个惊人的答案。

在 Edge 的启动快捷方式后面附上参数
--disable-features=msEEPageClassifier
之后,就会恢复正常。

实测有效!

想不通?对把,想不通就对了,因为我也想不通。

此参数的意思至今不明,截至 UTC+8 2022-06-21 22:38 为止,所有搜索引擎均无此参数的解释。个人猜测是 Edge 的某个内部私有参数。

设置此启动参数后重启 Edge (可以通过 edge://version 确认参数是否有效) 之后就能消除此故障,经过测试,所有用户加此参数后都无法再复现此故障。

根据群众猜测,从参数名来看,或许是页面内容(统计学意义上的)分类量化(存储以备后用),但这也无法确定。毕竟没有任何搜索引擎有结果告诉我们答案。

那么这篇博文的意义是什么?

  • 督促微软赶紧修复这个 Bug!
  • 如果有高人能完整解剖这个故障的成因,那就再好不过,了却我一桩疑惑。
  • 方便有人遇到同类故障的时候,可以搜索到本博文。
  • 如果你有兴趣,也可以前往 Linodas 随意的玩一玩。

将PHP版本从5.6升级到7.3中遇到的坑汇总贴[不定时更新]

提示:这是一篇技术博客,请普通玩家不必关注此文。

因为种种主观和客观原因,虽然我写的其他程序都是基于PHP7的了,但 Linodas 因为历史遗留太多,一直没有升级到最新的PHP版本,一直保持在5.6版本。

不过由于最近的一些神秘计划,因此在最近就正好将PHP更新到了CentOS 6.8支持的最高的7.3版。搬迁之后马上就遇到了一大堆问题。

因此,下面就是一份维修记录,除了作为技术留底,也方便了今后有人在网上搜索同类问题的时候能看到此文。

安装完php7之后记得装其他组件。

比如GD库,Redis等等。否则会报错找不到class

PHP7不再支持传统的 mysql_ 开头的库,需要用mysqli_ 开头的替换

注意不能直接复制粘贴替换,否则会死的很惨。
可以先用 http://www.seabreezecomputers.com/mysql2mysqli/ 这个工具转换旧的代码,注意也不要直接转换完了就替换,也会死得很惨。
请务必要针对自己的mysql库的实际情况(OO化的还是过程化的),具体调整代码才可以工作。

=& new classname 不能用

直接删掉&即可

一般个人不会用这种写法,我是改一个第三方库里面的

PHP7不支持 preg_replace 中使用 /e 修饰符,需要用 preg_replace_callback 替换

这里一定要小心的修复,我在这里遇到的问题是模板引擎太老,导致所有模板生成全是空白,查阅error_log没有报错,所以花了许多时间解决这个问题。

现在一般大家写的时候都不会用/e修饰符了,所以问题不大。

NaN和False的关系

用一张图可以说明此问题

对于有多个PHP版本情况,记得要修改crontab中的CLI方式执行的PHP文件

例如在cron中如果有类似
/usr/bin/php /www/domain/123.php
这样的内容,需要修改为类似
/usr/bin/php73 /www/domain/123.php
这样。

类似 $aaa->$bbb[‘ccc’]的格式的解析顺序变化

这个一般很多迁移指南里面都写为第一条,我当时感觉“啊好像我游没有用到这个写法啊”就没管。

结果还是中招了,不过只有一个很小的地方遇到了,问题不大,改了就好。

可以用下列正则快速的找出问题代码
\$[A-Za-z0-9]+\-\>\$[A-Za-z0-9]+\[
修改办法也很简单,改为
$aaa->{$bbb['ccc']}
就可以了

之后还会有更多更新,敬请期待。