Google Lighthouse Speed Index 100% 视觉上完成的帧定义

Google Lighthouse Speed Index 100% visually completed frame definition

我正在寻找一种方法来优化我们网站在 Lighthouse

上的 速度指数 指标

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

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

但是文章中有一个关键概念没有描述清楚,我搜索了很多其他Speed Index相关的博客也没有找到答案。

What is the 100% visual completeness frame?

我们都知道First Frame是0%VC因为它是空白的,但是VC在页面加载过程中一直在增加,所以呢框架将被视为 100% 视觉完整性?

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

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

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

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

因此,如果页面快速加载视图中的数据,但呈现“非首屏”内容(例如屏幕外图像)的速度较慢,那么即使页面整体加载时间仍然很长,您的视觉效果也会很快.

类似地,如果屏幕上的大部分内容都是在早期绘制的,而一小部分是在稍后绘制的(可能是“点击聊天”选项),那么您将在早期获得大部分视觉效果,因此速度指数很好,即使如果不如上面的例子。

另一方面,如果您最后加载字体或大型主图,并且它会重新绘制视图中的大部分页面,您将获得较慢的视觉完成时间和较慢的速度索引分数。

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

我刚从 Lighthouse 回购贡献者那里得到答案,请检查这个 link 伙计们。

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

灯塔

根据Google's description of the Lighthouse "Speed Index" audit

Lighthouse uses a node module called Speedline to generate the Speed Index score.

发送 Speedline

Speedline's Github readme

The Speed Index, introduced by WebpageTest.org, aims to solve this issue. It measures how fast the page content is visually displayed. The current implementation is based on the Visual Progress from Video Capture calculation method described on the Speed Index page. The visual progress is calculated by comparing the distance between the histogram of the current frame and the final frame.

(斜体是我的。)

绘画时间轴

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

In the case of Webkit-based browsers, we collect the timeline data which includes paint rects as well as other useful events.

我相信 "timeline data" 指的是通过 Performance Timeline API.

检索到的 JSON 对象

Lighthouse 似乎将 JSON 时间轴传递给 Speedline,其中 then extracts 一个 "frames," 数组描述了页面加载的绘制事件:

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

计算直方图

Speedline 将每个绘画事件的图像数据转换为 an image histogram,有趣的是排除了 "close enough" 的像素以作为白色传递:

/**
 * @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;
}

计算和比较直方图需要大量数学知识。项目维护者是询问这个问题的合适人选。但这是最终 determination of the "visually complete" happens:

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

并推断出 "progress"、

给定帧的"progress"好像是用这个函数计算的:

/**
 * @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;
}

并且"visually complete"是第一个进度为100%的帧。

在没有完全审核代码的情况下,我的解释是 "visually complete frame" 是第一个计算出与初始帧和最终帧具有相同总差异的帧(由哪些帧决定 Lighthouse chooses to send to Speedline).

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