DarkRiDDeR11 мин

Красный component при зелёном total: как сузить диагностику бюджета пути

ПроизводительностьFrontend

На пользовательском пути есть неприятный случай: общий total остаётся зелёным, но одна именованная часть пересекает свой допуск. Его легко списать как «небольшое колебание», особенно если pipeline не упал. Цена такого решения — диагностический долг. Следующее изменение добавит ещё немного работы, а у команды останется только общий график и спор о том, когда именно путь начал меняться.

Нужно не искать виноватого по одной строке, а правильно ограничить вывод. В учебной fixture candidate имеет total 93 при aggregate allowed 98, но scriptTicks равен 34 при allowed 30. Этот факт достаточен, чтобы заблокировать contract test, и недостаточен, чтобы объявить глобальную деградацию, проблему браузера, user metric или SLA. Хороший диагностический маршрут оставляет оба предложения рядом.

Сначала отделите три разных состояния

Первое состояние — comparable PASS: baseline и candidate имеют одинаковый contract, и все component checks проходят. Второе — comparable FAIL: contract тот же, но хотя бы один named component больше allowed. Третье — not comparable: scenario или conditions изменились, поэтому budget verdict не строится. Самая опасная ошибка — превратить третье состояние во второе. Тогда случайная смена cache, route data или config выглядит как performance regression, хотя данных для такого вывода нет.

Fixture показывает все три ветки. Baseline сравнивается сам с собой и проходит. Candidate с теми же conditions падает по scriptTicks. Отдельный candidate меняет только cache с outside-example на changed-training-cache-state; его comparison получает measurement-contract-invalid. В этой ветке нет component failure, потому что программа отказалась подменять различие условий числовым verdict.

Три диагностических состояния budget comparison
СостояниеЧто известноЧто не известноСледующий шаг
Comparable PASSвсе names внутри allowed при одном contractчто путь быстрый для всех пользователейсохранить snapshot и повторить только при том же contract
Comparable FAILодин named component превышает limit+toleranceглобальная причина или browser effectсобрать один факт на границе failed component
Not comparablecontract baseline/candidate различаетсяесть ли регрессиявосстановить scenario и conditions до нового compare
Aggregate PASS + component FAILtotal в пределах, name не в пределахчто component можно игнорироватьсчитать overall FAIL и сузить действие

Прочитайте output в правильном порядке

Первой строкой читается validation: comparable ли объекты. Второй — список failedComponents. Третьей — diagnosis, где field и scope явно ограничены. Aggregate читается последним: он объясняет общий запас, но не принимает решение. Такой порядок помогает reviewer не споткнуться о знакомое зелёное слово PASS. В fixture aggregate находится в candidateComparison.aggregate, а final decision — в candidateComparison.overall.

import { runPerformanceBudgetFixture } from "./upgrade-2022-02.mjs";

const { candidateComparison } = runPerformanceBudgetFixture();
const { diagnosis, measurementConditions } = candidateComparison;

console.log(diagnosis.kind);
// named-component-over-budget
console.log(diagnosis.component);
// scriptTicks
console.log(diagnosis.nextAction);
// inspect-script-input-and-one-route-boundary

if (measurementConditions.browserObservation !== "unavailable-in-example") {
  throw new Error("fixture must not pretend to hold a browser observation");
}

// The result narrows a next check; it is not a global speed claim.

Поле diagnosis.nextAction сознательно скупо: inspect-script-input-and-one-route-boundary. Оно не говорит «удалить библиотеку», «переписать приложение» или «ускорить сервер». По одному учебному числу нельзя выбрать такую архитектуру. Следующее действие должно породить проверяемый факт: например, список route inputs, diff зависимостей или отдельный профиль, если он действительно доступен и собран по понятному протоколу.

const next = runPerformanceBudgetFixture().candidateComparison;

if (next.diagnosis.component !== "scriptTicks") {
  throw new Error("do not widen investigation without a new observation");
}
console.log(next.overall.failedComponents);
// ["scriptTicks"]

Диаграмма: зелёный total не отменяет красную ветку

Диагностическая схема для budget comparison: сначала проверяются route, scenario и declared conditions; при несовпадении сравнение останавливается. При совпадении component checks идут раньше aggregate. Ветка scriptTicks 34 при allowed 30 ведёт к focused action, хотя total 93 при allowed 98 остаётся зелёным.
Схема показывает границы вывода: red component создаёт контрактный fail и ограниченную проверку, но не доказывает глобальную скорость, trace браузера или пользовательский результат.

Маршрут: симптом → причина → проверка → действие

  1. Симптом. Total budget зелёный, но на маршруте появляется новый красный component или его запас постепенно сокращается.
  2. Причина. Итоговая сумма скрывает распределение. Либо baseline/candidate стали несопоставимыми, и цифры вообще нельзя читать вместе.
  3. Проверка contract. Сверьте route, scenario, workloadVersion, unit и every declared condition. При любом различии получите measurement-contract-invalid, а не performance verdict.
  4. Проверка component. Запишите actual, limit, tolerance и allowed. В этом case scriptTicks 34 против allowed 30; named fail остаётся виден независимо от total.
  5. Проверка aggregate. Используйте 93 против allowed 98 только для контекста: total не вышел за вторичный guard, но он не может перевести overall в PASS.
  6. Действие. Сохраните failed name и возьмите один input плюс одну boundary для следующего наблюдения. После изменения повторите тот же compare; если contract изменился, оформите новый snapshot.

Как не сделать из диагностики глобальный performance verdict

У diagnosis есть поле notClaim. Оно явно запрещает интерпретировать результат как global speed, browser trace, real-user result или SLA verdict. Такое ограничение кажется избыточным, пока в отчёте не появляется знакомое число. Именно тогда человек склонен достроить историю: «34 значит страница медленнее». Нет. В fixture 34 — значение одного условного property при локальном object comparison. Оно говорит ровно то, что проверено: rule именованной части не соблюдён.

Нужен и обратный запрет. Aggregate PASS не даёт сказать «проблемы нет». Он лишь говорит, что учебный total не пересёк свой aggregate allowed. В реальном проекте этот total может быть полезен как guard против общего роста, но не как единственный gate. Если граница пользователя критична, ей нужен собственный named contract и owner. Если она не критична, тогда лучше не притворяться, что общий score защищает её.

Выберите границу следующего наблюдения

Для scriptTicks не стоит сразу открывать весь application. Начните с route boundary: entry, bundle boundary, dynamic input или другой реальный владелец, который выбран в mapping. Одного артефакта достаточно, чтобы сузить или отвергнуть гипотезу. Если видно, что changed input не относится к route, вернитесь к contract. Если input относится к route, тогда можно подготовить небольшое обратимое изменение и повторить compare. Оба пути лучше, чем широкая «оптимизация производительности».

Подход сохраняет практический опыт 2022 года: сначала пользовательский опыт и наблюдаемый контракт, затем система границ, затем решение с ценой. Он не делает вид, что автор владеет production telemetry или знает реальную причину без trace. Любой более сильный вывод требует нового доказательства. Это не осторожность ради тона — это способ не закрепить неверную архитектуру после одной зелёной или красной строки.

Источники помогают не перепутать поля

W3C Navigation Timing Level 2 в историческом snapshot описывает platform interface для navigation data. User Timing Level 3 описывает marks/measures и metadata. Performance Timeline Level 2 описывает retrieval performance entries и observer mechanics. В каждом случае источник помогает понять, что значит фактическое поле платформы. Но он не говорит, что scriptTicks fixture равно одному из этих полей или что эти поля уже собраны в этом проекте.

Перед переносом модели на настоящую страницу полезна маленькая таблица mapping: field учебного контракта, concrete source, data availability, transform, owner и known limitation. Если для одного поля mapping отсутствует, не подставляйте похожий термин. Либо оставьте field учебным, либо сначала соберите новый evidence. Такая дисциплина защищает не только от анахронизма, но и от обычной ошибки: неправильная метрика даёт очень точное число и очень плохое решение.

Сигнал для CI и отдельный сигнал для исследования

CI gate может работать как контрактный предохранитель: сравнить known snapshot и candidate, вывести failed components и завершиться с ошибкой. Но не стоит называть этот outcome «измерением браузерной производительности», если job не выполнял такое наблюдение. В fixture CI observation честно указано как unavailable-in-example. Так автоматизация остаётся полезной, но не получает чужой смысл.

Исследование начинается после fail, а не до него. Для него нужны реальные артефакты, которые отсутствуют в fixture: выбранный browser profile, trace, resource list, application markers или другой источник. Их нельзя выводить из teaching ticks. Напротив, contract budget делает исследование дешевле: он уже назвал route, scenario, failed component, owner boundary и запретил смешать условия. Значит следующий сбор материала может быть меньше и точнее.

Что проверить после focused action

После небольшого изменения не повышайте limit первым движением. Сначала повторите same contract compare. Если scriptTicks вернулся в allowed, зафиксируйте, какой input изменился и что всё ещё не известно. Если не вернулся, следующий шаг должен быть ещё одним проверяемым узким экспериментом, а не каскадом правок. Если route or scenario изменились, не сравнивайте с исходным baseline: оформите новую версию workload и причину пересмотра.

Историческая граница февраля 2022

Материал не использует будущие показатели взаимодействия и не ссылается на актуальные страницы, которые могли поменять советы. Ссылки ниже ведут на dated W3C drafts: январь 2022 для Navigation Timing и 2021 для User Timing и Performance Timeline. Все три документа различают официальные platform interfaces и этап working draft. Учебная диагностика поверх них остаётся собственной моделью пакета.

Проверяемые источники