Маяк
Согласно описанию Google маяка «Индекс скорости» аудита :
Lighthouse использует модуль узла под названием Speedline , чтобы сгенерировать показатель индекса скорости.
отправляет Speedline
Readme Github Speedline говорит
Индекс скорости , представленный WebpageTest.org , призван решить эту проблему. Он измеряет как быстро визуально отображается содержимое страницы . Текущая реализация основана на методе вычисления Visual Progress from Video Capture , описанном на странице Speed Index . Визуальный прогресс вычисляется путем сравнения расстояния между гистограммой текущего кадра и последнего кадра.
(Курсив мой.)
Хронология красок
Страница индекса скорости содержит болезненных подробностей о том, как вычисляется визуальный прогресс. Вот фрагмент кода:
В случае браузеров на основе Webkit мы собираем данные временной шкалы, которые включают в себя фрагменты рисования и другие полезные события.
Я полагаю, что "данные временной шкалы" относятся к объекту JSON, полученному с помощью Performance Timeline API .
Кажется, что 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;
}
Много математики идет на вычисление и сравнение гистограмм. Сопровождающий проекта - это тот человек, который хочет спросить об этом. Но именно здесь происходит окончательное определение «визуально завершенного» * 1064 *:
// 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 ).
Или, другими словами, это сложно .