1

我正在寻找一种方法来优化我们网站在 Lighthouse上的速度指数指标

我发现这篇有用的文章很好地描述了速度指数指标,并帮助我了解如何计算速度指数。

https://calendar.perfplanet.com/2016/speed-index-tips-and-tricks/

但是有一个关键概念在文章中没有描述清楚,我搜索了很多其他速度指数相关的博客仍然找不到答案。

什么是100% 视觉完整性框架

我们都知道第一帧是 0% VC,因为它是空白的,但是在页面加载过程中 VC 不断增加,那么什么帧会被认为是100% 的视觉完整性

100% VC 帧的定义很重要,因为它是计算所有其他帧的视觉完整性的基线。

如果我有一个页面以 100 毫秒的间隔简单地从 1 打印到 100 并且刚好足以填充视口,那么100% VC 帧会是打印数字100的帧吗?

4

3 回答 3

3

灯塔

根据谷歌对灯塔“速度指数”审计的描述

Lighthouse 使用名为Speedline的节点模块来生成速度指数分数。

发送 Speedline

Speedline 的 Github 自述文件

WebpageTest.org推出的速度指数旨在解决这个问题。它衡量页面内容在视觉上显示的速度。当前的实现基于Speed Index页面上描述的视频捕获的视觉进度计算方法。通过比较当前帧的直方图与最后一帧的距离来计算视觉进度。

(斜体是我的。)

颜料的时间线

速度指数页面详细介绍了如何计算视觉进度。这是一个片段:

对于基于 Webkit 的浏览器,我们收集时间线数据,其中包括绘制矩形以及其他有用的事件。

我相信“时间线数据”是指通过Performance Timeline API检索到的 JSON 对象。

似乎 Lighthouse 将 JSON 时间线传递给 Speedline,然后提取一组“帧”,描述页面加载的绘制事件:

/**
 * @param {string|Array<TraceEvent>|{traceEvents: Array<TraceEvent>}} timeline
 * @param {Options} opts
 */
function extractFramesFromTimeline(timeline, opts) {

计算直方图

Speedline 将来自每个绘制事件的图像数据转换为图像直方图,有趣的是排除了“足够接近”以作为白色传递的像素:

/**
 * @param {number} i
 * @param {number} j
 * @param {ImageData} img
 */
function isWhitePixel(i, j, img) {
    return getPixel(i, j, 0, img.width, img.data) >= 249 &&
            getPixel(i, j, 1, img.width, img.data) >= 249 &&
            getPixel(i, j, 2, img.width, img.data) >= 249;
}

很多数学都用于计算和比较直方图。项目维护者是询问这个问题的合适人选。但这是最终确定“视觉完整”的地方:

// find visually complete
for (let i = 0; i < frames.length && !visuallyCompleteTs; i++) {
    if (frames[i][progressToUse]() >= 100) {
        visuallyCompleteTs = frames[i].getTimeStamp();
    }
}

并推断“进展”,

给定帧的“进度”似乎是由这个函数计算的:

/**
 * @param {Frame} current
 * @param {Frame} initial
 * @param {Frame} target
 */
function calculateFrameProgress(current, initial, target) {
    let total = 0;
    let match = 0;

    const currentHist = current.getHistogram();
    const initialHist = initial.getHistogram();
    const targetHist = target.getHistogram();

    for (let channel = 0; channel < 3; channel++) {
        for (let pixelVal = 0; pixelVal < 256; pixelVal++) {
            const currentCount = currentHist[channel][pixelVal];
            const initialCount = initialHist[channel][pixelVal];
            const targetCount = targetHist[channel][pixelVal];

            const currentDiff = Math.abs(currentCount - initialCount);
            const targetDiff = Math.abs(targetCount - initialCount);

            match += Math.min(currentDiff, targetDiff);
            total += targetDiff;
        }
    }

    let progress;
    if (match === 0 && total === 0) {   // All images are the same
        progress = 100;
    } else {                                                    // When images differs
        progress = Math.floor(match / total * 100);
    }
    return progress;
}

并且“视觉上完成”是具有 100% 进度的第一帧。

在没有完全审核代码的情况下,我的解释是“视觉上完整的帧”是计算出来的第一帧,其与初始帧的总差异与最终帧的总差异相同(这取决于Lighthouse 选择发送到 Speedline的帧)。

或者,换句话说,它很复杂

于 2019-04-11T13:27:11.947 回答
2

视觉完整是指视口中的页面停止更改。即视觉效果没有改变。

它是通过在整个加载过程中截取屏幕截图并将它们相互比较以及与最终结束状态进行比较来计算的。因此,在您的示例中是的,当打印所有数字 1-100 并且页面停止更改时,您“视觉上是完整的”。

因此,如果一个页面快速加载视图中的数据,但渲染“非首屏”内容(例如屏幕外图像)的速度更慢,那么即使页面整体加载时间仍然很长,您也将获得快速的视觉完整性。

同样,如果屏幕上的大部分内容是早期绘制的,而一小部分是稍后绘制的(可能是“点击聊天”选项),那么您将在早期获得大部分视觉上的完整,因此即使不如上面的例子。

另一方面,如果你加载字体,或者可能是一个大的英雄图像,最后它会重绘页面的大部分,你会得到一个缓慢的视觉完成时间和一个缓慢的速度索引分数。

更多详细信息:https ://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index

于 2019-04-10T20:37:31.903 回答
0

我刚刚从 Lighthouse repo 贡献者那里得到了答案,请检查这个链接。

https://github.com/GoogleChrome/lighthouse/issues/8148

于 2019-04-11T08:37:09.793 回答