20 KiB
tags, updated, status
| tags | updated | status | |||
|---|---|---|---|---|---|
|
2026-10-30 | analysis |
CPM iOS: оставшиеся группы и следующий фокус — 30 октября 2026
Продолжение: cpm-ios-idle-wake-investigation-2026-10-30 — browser actions, shipped app/extension/WebKit paths, проверка storage/state queue, публичные аналоги и конкретный telemetry proposal. Уточнение интерпретации M4: reload_state=loaded без квалифицирующего нового замера не доказывает провал messaging recovery; отдельно выделены response_timed_out и предложен post-recovery opportunity counter.
Обновлён ClickHouse-срез и проверены актуальные PR. Следующий основной фокус — потеря ответа после idle wake при уже готовом фоне; второй — старт с pending без текущей error 6. Отдельно остаётся непроверенный хвост error-6 history → replacement view → pending: его нельзя объявлять закрытым #7730. Это выбор следующего расследования и исправления по наблюдаемым симптомам, а не доказанная причинная классификация.
macOS в этом пересчёте не анализировалась.
Данные и проверка
Источник: Grafana ClickHouse datasource dekdbd6bqq1hcd, metrics.pixels, agent ddg_ios, pixel_id web, web.extension.cpm.episode.{count,daily}.ios.{phone,tablet}.
Запрос episodes выполнен 30 октября 11:01:52 UTC / 17:01:52 Бишкек. Проверка свежести: последние события — 10:50:01 UTC / 16:50:01 Бишкек. Серверная timezone независимо проверена: America/New_York. Все даты ниже — metrics.date, то есть Eastern; 30 октября — незавершённый день, а не полный UTC-день.
Выгружена последняя неделя, 23–30 октября. Основной анализ — 7.243.0, 26–29 октября, отдельно последний завершённый день 29 октября и частичный 30 октября. 23–25 октября содержат только семь count-событий до публичного релиза и исключены из production-приоритетов. У 7.244.0 найдены лишь два count-события 29 октября; это не выборка эффекта сегодняшних фиксов. Различить public/internal traffic внутри версии по этим полям нельзя.
Обработаны 404 222 агрегированные строки. За 26–29 октября: 477 214 count-эпизодов, 305 853 первых дневных отчёта, 15 576 подтверждённых cross-tab no-response эпизодов, 5 902 таких первых дневных отчёта.
Независимый SQL повторяет классификацию на сервере; второй контроль проверяет исходы без неё. Завершённые дни сошлись точно, проверены 336 значений групп по окнам и метрикам. На 30 октября последовательные запросы расходятся из-за продолжающейся загрузки событий, даже при ограничении event timestamp. Числа частичного дня привязаны к сохранённому export, а не представлены как неизменяемый snapshot базы.
Определения:
no_response:outcome=no_response_before_deadline, окно около пяти активных минут. Это не доказательство вечной поломки.- Подтверждение:
repeat_failures=1/2+илиreload_state≠none. - Cross-tab:
tabs_affected=2/3+, плюс no-response и подтверждение выше. count— эпизоды.daily— первый завершившийся эпизод установки за день; это нижняя оценка тяжёлых случаев, а не «хотя бы один тяжёлый сбой за день». Сумма по дням — install-days, не уникальные пользователи недели.- Ответ закрывает эпизод, но не доказывает доставку initResp каждой ранее падавшей вкладке.
Приоритет непересекающихся групп сохранён из предыдущего разбора: error 6 в текущем поле или истории → no view → нет scripts/controller mismatch → update <2 мин → idle wake → context load/baseURL change <2 мин → other. @30s означает возраст меньше 30 секунд, @2m — меньше двух минут. Возраст view дополнительно проверяется по bg_view_age.
Последний полный день: 29 октября
Всего 364 695 эпизодов, из них 9 849 подтверждённых cross-tab no-response; на daily-leg — 4 090 соответствующих первых дневных отчётов.
Доли ниже — от этих 4 090 daily-отчётов; число эпизодов указано отдельно:
- Idle wake: 1 331 / 32,5%; 2 920 эпизодов.
- Recent context load: 841 / 20,6%; 1 710 эпизодов.
- Error 6, включая историю: 712 / 17,4%; 2 818 эпизодов.
- Extension updated: 559 / 13,7%; 571 эпизод.
- No background view: 342 / 8,4%; 760 эпизодов.
- Other: 305 / 7,5%; 1 070 эпизодов.
- Tab disconnected/P6: 0 daily, 0 cross-tab эпизодов; 15 подтверждённых no-response эпизодов без cross-tab условия.
Первые две группы дают 53,1% таких daily-отчётов. Wake + other — 40,0%, но это не доказанный объём одного механизма.
На частичном 30 октября в сохранённом export: 106 436 эпизодов, 3 317 подтверждённых cross-tab no-response; 1 322 соответствующих daily-отчёта. Wake — 372 / 28,1%, recent load — 306 / 23,1%, error 6 — 224 / 16,9%. Это поддерживает порядок приоритетов, но внутридневные частоты с полным днём не сравниваются.
1. Idle wake: крупнейшая группа без отдельного целевого исправления
Все следующие footprints относятся к 2 920 cross-tab подтверждённым no-response count-эпизодам 29 октября.
Форма: dealloc → view → proxy_on, часто несколько циклов. У 2 688 / 92,1% bg_ready_after=under_1s; у 2 774 / 95,0% все восемь native-флагов true. Это делает «просто долго грузился background» слабым объяснением основной части этой группы. Native readiness не проверяет listener и доставку конкретного init/ответа.
660 / 22,6% имеют только повторяющиеся dealloc>view>proxy_on в доступной истории, без load, origin change, update, interruption, died или error. Это видимый минимум немаркированного ядра; в 2 038 / 69,8% всей wake-группы история достигает 12 токенов, поэтому отсутствие старого события ничего не доказывает.
В истории died_client есть у 420 / 14,4%, died_crash — у 72 / 2,5%; ни один из них не объясняет большинство. interruption в истории встречается у 1 660, но interrupted=true самого первого замера — лишь у 50: это разные признаки. У 776 после M4 зафиксирован reload_state=response_timed_out; смена контекста сама по себе не гарантировала ответ.
Что исследовать для следующего фикса: путь первого init после idle/resume при background-ready <1 s: дошёл ли init в worker, завершились ли native вызовы, был ли dashboard response и почему он не атрибутировался. Затем — bounded retry/re-init или другая recovery только для воспроизведённого разрыва. Простые длинные idle-тесты ранее были чистыми; повторять только их недостаточно. Нужен сценарий iOS resume/navigation и совпадение footprint.
1 275 из этих эпизодов на OS <26.6; stable-origin policy там не применяется. Но и на 26.6+ wake не становится автоматически покрытым P3.
2. Старт остаётся отдельным крупным кандидатом; recent load нельзя целиком вычесть как P3
Из 1 710 cross-tab эпизодов recent load 1 241 без base_url_changed в истории, и 1 065 из них с текущим background pending. На daily-leg соответствующий pending-поднабор — 585 первых дневных тяжёлых отчётов. Типичная короткая история: load@30s,view@30s,proxy_on@30s. У всей recent-load группы только 463 эпизода уже имели readiness <1 s.
P3 устраняет подтверждённые задержки очистки данных при смене origin; эти симптомы могут частично улучшиться. Однако recent load не является причинной меткой P3, а отсутствие base_url_changed не исключает origin cleanup при первом контексте процесса: token сравнивает контексты только внутри текущего процесса.
Следующая проверка после rollout P3 — pending startup отдельно от ready/no-response, с OS <26.6 / 26.6+ и фактическим состоянием флага. P4 late-document recovery в известной конфигурации default OFF; startup_response_missing — detection, не применённое лечение. На 26–29 октября найдено 226 933 count detection-события, но без ключа связи с эпизодом это не размер исправляемой тяжёлой группы.
3. Весь error-6 cohort не закрывается PR #7730
29 октября из 2 818 cross-tab эпизодов этой группы:
- 508 имеют текущую атрибутированную error 6 в
bg_load_error_after. - 2 310 имеют error 6 только в истории.
- 2 276 из этих 2 310 уже относятся к новому текущему view с readiness
pending; daily-leg этого поднабора — 311. - 1 929 имеют не меньше двух error-токенов в хвосте истории.
Частый pattern: dealloc → error_6 → view → proxy_on, повторённый несколько раз. В коде создание нового view очищает текущую атрибуцию load error, но сохраняет lifecycle history. Поэтому broad error-6 group существенно шире «нынешний view упал с error 6».
#7730, OPEN, head cf668e2938: restart того же failed view, если он ещё удерживается; released view сохраняет P2 retry, replacement view намеренно не трогается. PR также исправляет deferred/cooldown scheduling и дедупликацию старых ошибок.
Остаток не доказанно закрыт, но и точный uncovered share из этих чисел не выводится: нет identity failed/replacement view на момент принятия recovery-решения, событий после первого snapshot и связанного outcome treatment. Повторный error token в старом recorder не обязательно означает новую независимую ошибку.
Нужен отдельный OFF/ON сценарий с released failed view → новый view → pending на точном #7730. Если он остаётся красным, следующий фикс относится к stalled replacement load, а не к ещё одному restart уже покрытого retained view.
4. Other и no-view
Other: 1 070 cross-tab эпизодов; у 863 readiness <1 s. Часто это те же idle-циклы, но текущему view уже 30 s–2 min, поэтому жёсткая граница wake классификатора переносит их в other. Это возможное продолжение того же пути потери init; считать одинаковую причину установленной нельзя.
No-view — 158 115 / 43,4% всех эпизодов 29 октября, но только 760 / 7,7% тяжёлых cross-tab эпизодов. Для 151 232 / 95,6% no-view эпизодов зарегистрирован какой-либо последующий ответ. Группа смешивает свежий load без view и уже работавший фон после dealloc. Большой объём transient failures не делает её первой целью исправлений browser-wide no-response.
Что уже учтено как покрытие
- #7753 MERGED в
release/ios/7.244.0; фильтр error documents и итоговые OS/flag ограничения stable origin. Это merge в будущий релиз, не измеренное исправление текущего 7.243.0. P3 #7493 уже merged; runtime effect зависит от версии, OS и включения stable-origin флага. - #7767 OPEN, head
45593bbb4e: CPM upgrade-before-load на запуске; private origin переносится только при допустимой policy и отсутствии живого старого контекста. Хорошее целевое покрытие launch-upgrade пути, но не всех событийextension_updated, всех runtime upgrades или всех startup hangs. - #7730 — retained failed view и scheduling, с ограничениями выше.
- #7784 — instrumentation времени navigation readiness; поведение CPM recovery не исправляет.
- #7385 — полезная идея init progress, но PR всё ещё stacked на закрытом #7384 и описывает прежний контракт. Это не готовое покрытие текущих episodes; перенос требует адаптации к действующей схеме и extension bundle.
- P6 на iOS сейчас практически не влияет на cross-tab результат. Graveyard не обоснован этим wake-срезом.
Production effect ни одного нового PR этим анализом не измерен. Широкие symptom cohorts нельзя вычесть из знаменателя как будто все входящие эпизоды уже исправлены.
iOS error pages: уточнение к прежним заметкам
В cpm-post-release-analysis-2026-10-27 осталось утверждение, что iOS runtime не проверялся. Есть более свежая отдельная проверка 29 октября: реальный diagnostic app на iOS 26.5/27.0, DNS и connection-refused отменяли замер; SSL и phishing предупреждения получали CPM dashboard response; после idle также не было episodes/M4. Подробности: iOS runtime report.
Это поддерживает отдельный iOS-анализ. Проверка была simulator/dev-build, не полный набор физических устройств и не доказательство отсутствия любых false positives.
Рабочая последовательность
- Завершить уже подготовленные #7730 и #7767 по их существующему scope.
- Новая основная ветка исправлений: iOS idle/resume → init delivery/response attribution при уже ready фоне. Одновременно отделять совпадающий other.
- Второй трек: pending startup без текущей error 6; измерить остаток после включённого P3 и воспроизвести потерянный первый документ, прежде чем менять late recovery.
- Параллельная проверка границы #7730: historical error 6 → replacement pending. Расширять recovery только после совпадающего воспроизведения.
- Для разграничения причин нужны init-stage evidence и события после первого failure. Нынешний
bg_events— только snapshot начала эпизода, один phase, максимум 12 событий / 255 символов; он не показывает развитие сбоя и результат конкретного retry.
Воспроизводимость
Локальный каталог: /Users/admin/DuckDuckGo/apple-browsers.git/cpm-ios-groups-2026-10-30/.
episodes.sql/.tsv/.json— агрегированная выгрузка, без install/session IDs и URL страниц.inventory,freshness,controls,group_verification— SQL, raw responses и TSV контрольных запросов.denominators_26…30— запросы отдельно по дням; единый пятидневный запрос превысил лимит 7B rows, после чего разбит на дни.treatments— события readiness/recovery/detection; связанного episode outcome в них нет.summary.json,groups.csv— разбивки по count/daily, окнам, состоянию, OS и footprints.analyze.py,verify.py,query.py— разбор, независимая сверка и read-only runner.pr-*.json— проверенный GitHub snapshot состава и scope PR.verification-result.json— точное совпадение завершённых дней и отдельно drift текущего дня.
Код приложения, remote config и PR не менялись; внешним участникам данные не отправлялись.