Всё о проекте «Спутниковый интернет». Часть 40. Испанский «привет» СтарЛинку

Предлагаю ознакомиться с ранее размещенными материалами по проекту StarLink (SL):

Часть 30. Сравнение сервиса StarLink с сервисами других операторов ШПД
Часть 31. Описание антенны Ка-диапазона
Часть 32. Проблемы терминалов StarLink из-за перегрева
Часть 33. Прошивка Терминала
Часть 34. SpaceX планирует купить компанию SWARM
Часть 35. Проблема StarLink и LEO группировок
Часть 36. Ретроспектива частотных планов
Часть 37. НеДовыход из бета-версии и проблемы с выполнением предзаказов
Часть 38. Новый терминал StarLink UT-2
Часть 39. Эволюция частотных планов StarLink в 2016-2020 годах

Так как я весьма тщательно слежу за проектом StarLink, и даже собираюсь стать его абонентом, то меня очень удивила задержка с началом сервиса в Испании, которая в отличие от всех крупных европейских стран, стала доступной для подключения только в декабре 2021 года, несмотря на то, что гейтвей в Мадриде был готов еще в середине года (а всего их в Испании уже три).
Испания страна достаточно сельская, и в горных районах иногда и просто телефон не ловит сигнал, не говоря про LTE, и причина задержки начала сервиса оказалась весьма неожиданной и для меня, и, как я понимаю, для Илона Маска.
Все стало понятно, когда один из потенциальных абонентов опубликовал скан своего будущего счета за сервис:

Получается, что к стандартной плате в Европе в 89 Евро в месяц (аналог 99 Долларов), абонентам в Испании добавится еще 9 Евро в месяц (то есть +10%), и причина этого-необходимость оплатить радиочастный спектр.
Перевод текста на белой плашке
«налагает значительную стоимость лицензии на доступ к электромагнитному спектру, необходимому для предоставления услуг. Подробнее о плате за резервирование радиоэлектрического общественного достояния я могу прочитать в проекте общих бюджетов государства на 2022 год.»

Получается, что власти Испании, страны небогатой и сильно пострадавшей от Ковида (14% ВВП Испании- это туризм, а он рухнул на 70-80%), решили посмотреть какими природными ресурсами обладает страна и пришли к выводу, что в отсутствие нефти и газа, таковым является радиочастотный спектр. Деньги похоже будут платить все, кто использует его для получения дохода — с астрономов и пользователей wifi дома его точно не возьмут.
SpaceX видимо долго думал, что делать — может пытался убедить власти от этого отказаться, и похоже оказался не готов взять расходы на себя, решив перенести этот сбор на абонентов. Хотя это явно противоречит идее одного общемирового тарифа у СтарЛинк, так как скорее всего платежи на спектр есть во всех странах, но в Испании их видимо загнали в лицензию, которую надо оплатить однократно.

Отметим, что в Испании SpaceX использует по 2000 МГц в Ка и в Кu диапазонах.

А чтобы понять, какая ценная вещь этот спектр, вот Вам совсем новая информация о том, сколько в США операторы заплатили за частоты в нижнем С-band (частоты в районе 3,45 ГГц, который американский регулятор отбирает сейчас у спутниковой связи.
За 100 (!) МГц и право их использовать в одной небольшой географической зоне Оператор заплатил 1,7 млн., а всего FCC собрало за эти 100 МГц 22 (!) миллиарда Долларов.

Кстати, в РФ то же есть плата за радиочастотный спектр, для мобильной связи их размер весьма высок, но для VSAT и спутниковой связи действуют понижающие тарифы, и для бизнеса эти платежи не являются значительной нагрузкой.

Для тех, кто хочет поломать голову сколько надо заплатить за спектр — по ссылке rkn.gov.ru/communication/p552/p779 методика, действующая в России.

Я скажу, что это документ не для слабонервных, и справится с ним только отличник по математике.


ссылка на оригинал статьи https://habr.com/ru/post/646869/

HAQuDA: новый взгляд на мониторы качества воздуха

HAQuDA – это настольная лампа, которая отображает данные о параметрах окружающей среды: качестве воздуха, температуре и влажности, при помощи цвета освещения. Если параметр в норме, то он зеленый, а если завышен или занижен, то красный или синий соответственно. У лампы есть несколько режимов отображения: стандартный, мульти, ночной, режим светильника, и возможность управления с помощью собственной веб-страницы и голосовых помощников.


Всем привет! 

В период пандемии большая часть нашей жизни перестала выходить за рамки четырех стен, из-за чего остро встал вопрос о состоянии окружающей нас среды, о качестве воздуха в квартире, так как он напрямую влияет на наше самочувствие и продуктивность. В этой статье я хотел бы рассказать о процессе разработки волшебного домашнего отображателя качества воздуха.

С чего все началось…

В книге «Будущее вещей» Дэвида Роуза, автор рассказывает о свойствах волшебных вещей, способных облегчить нашу повседневную жизнь: часы с цветовым отображением количества потребленной электроэнергии в квартире, волшебный шар, способный цветом показывать совершенно разные параметры: от количества аллергической пыльцы на улице, до текущей стоимости акций. Почему эти вещи волшебные? Их концепции взяты из известных фантастических произведений. Судите сами: в повести Дж.Р.Р. Толкина «Хоббит, или Туда и Обратно» есть волшебный кинжал — «Жало», который кроме своей основной задачи — убивать полчища орков и гоблинов, еще и предупреждает своего хозяина о присутствии недругов — отличный пример простого интерфейса человек-устройство. Развитие идеи волшебных устройств воплотилось в  устройстве ОПЭДИ, которое отображает на календаре количество потребленной электроэнергии в квартире, в разработке которого и я принимал участие. Мне захотелось продолжить эту идею и я решил собрать станцию мониторинга качества воздуха, которая совмещала бы в себе все необходимые датчики и имела «волшебные» свойства. Так и родилась идея HAQuDA…

Для чего он нужен?

Основная идея устройства заключается в простоте передачи информации о состоянии дома человеку. Существующие модели датчиков качества воздуха передают информацию понятную специалистам, но специфичную для простых пользователей, например единица измерения CO2 – PPM, а количество летучей органики (формальдегиды, ацетон, этанол и т.д.)  измеряется в микрограммах на кубический метр. ОКВоДи позволяет моментально и понятно показывать информацию о качестве воздуха, за счет ее отображения цветом: от зеленого – качество воздуха хорошее, до красного — когда уже пора проветрить помещение. В этом устройстве заложен принцип “преаттентивности” (от англ. pre-attention) — показывать тот объем информации, который необходим для принятия решения, что позволит человеку быстрее обрабатывать информации, не фокусируя на ней внимание.

Примеры преаттентивных отображений данных
На тепловой карте акций по цвету сразу можно увидеть акции каких компаний теряют в цене, а по размеру у кого сумма акций больше
На тепловой карте акций по цвету сразу можно увидеть акции каких компаний теряют в цене, а по размеру у кого сумма акций больше
А на тепловой карте температуры можно сразу определить в каких регионах теплее, а в каких зима в самом разгаре
А на тепловой карте температуры можно сразу определить в каких регионах теплее, а в каких зима в самом разгаре

Как он устроен?

ОКВоДи представляет собой лампу цилиндрической формы (90×130мм) состоящую из двух частей: матовая полупрозрачная белая верхняя часть и основание из непрозрачного пластика. Внутри верхней части к трубе, закрепленной на плате, приклеены адресные светодиоды WS2812B, в количестве 12×9 штук. На плате расположены ESP-32 mini и датчики: датчик влажности и температуры – DHT-11, датчик летучих органических соединений и датчик угарного газа – CCS811, датчик озона — ZE25-O3, датчик взвешенных частиц — ZH03B. В верхней крышке расположена сенсорная кнопка, чтобы отслеживать касания и менять режим отображения. Также на плате располагается два USB-A выхода для зарядки устройств и один USB-Micro вход питания.

Основные функции

ОКВоДи умеет отображать следующие параметры микроклимата дома:

  • Летучие органические соединения (TVOC) – измеряется в частицах на миллиард [ppb]

  • Количество озона (O3) – измеряется в частицах на миллиард [ppm], ±0.01ppm

  • Твердые частицы PM1.0, PM2.5, PM10 (Dust) – измеряется в микрограммах на метр кубический [мкг/м3], ±15 мкг/м3

  • Углекислый газ (CO2) — измеряется в частицах на миллион [ppm]

  • Температура (Temp) – измеряется в градусах Цельсия [°C], ± 2℃

  • Влажность (Humid) – измеряется в процентах [%], ± 5%

  • Общее качество воздуха (TotalAirQuality) – рассчитывается на основе всех предыдущих показателей 

Выбор именно этих показателей качества воздуха связан с тем, что они оказывают основное долговременное воздействие на человека.

Режимы отображения:

  • Основной (Standard-mode) – все светодиоды задействованы для одного конкретного параметра

  • Мульти-режим (Multi-mode) – светодиоды делятся на три секции и отображают три параметра, выбранные пользователем

Пример мульти-режима: снизу температура, затем CO2, и пыль, как видно в комнате было достаточно тепло, а качество воздуха было в порядке
Пример мульти-режима: снизу температура, затем CO2, и пыль, как видно в комнате было достаточно тепло, а качество воздуха было в порядке
  • Ночной (Night-mode) – три вертикальные линии светодиодов выделяются под отображение одного параметра, заданного пользователем, остальные выполняют роль подсветки-ночника и отображают время преаттентивно: вертикальным заполнением полосы светодиодов. Пользователь вводит временной диапазон, например от времени засыпания, до будильника, по умолчанию установлен с 21.00 до 09.00. Каждый час загорается новая линия светодиодов, таким образом яркость ночника увеличивается с наступлением утра, а в промежутках сна можно определить оставшееся время чтобы поспать. В итоге получается progress bar времени вашего сна

Примеры ночного режима с отображением CO2
На этой картинке время примерно между 11-ю и 12-ю часами ночи, горят 2 белых светодиода
На этой картинке время примерно между 11-ю и 12-ю часами ночи, горят 2 белых светодиода
А на этой картинке уже утро - горят все светодиоды и количество CO2 уменьшилось
А на этой картинке уже утро — горят все светодиоды и количество CO2 уменьшилось
Пример ночного режима на 3D модели лампы
Пример ночного режима на 3D модели лампы

Приступаем к разработке

Разработку я начал с создания общей 3D-модели устройства, чтобы примерно определить его габариты, размеры печатной платы и количество светодиодов ,которые можно разместить внутри.

За основу корпуса решил взять небольшую лампу, потому что у нее был отличный рассеиватель и по размерам он подходил.В SolidWorks сделал 3D модель всей лампы с нижней частью корпуса, и со всеми отверстиями, чтобы понимать как разместить все компоненты в столь небольшом объеме.

3D-модель первой версии лампы
3D-модель первой версии лампы
А под спойлером вы можете увидеть, как лампа выглядит внутри
3D-модель лампы без корпуса и рассеивателя
3D-модель лампы без корпуса и рассеивателя

Схему проектировал с расчетом на то, что в будущем заменю готовый модуль D1 Mini ESP32 на оригинальный ESP WROOM 32, так как порт USB-micro на D1 Mini расположен в неудобном для круглого корпуса месте (его не выведешь наружу, он утоплен в плате) и при разработке ориентировался на прошивку и отладку с помощью JTAG-программатора, ну и готовый модуль занимает меньше места.Развел печатную плату в Altium-е и заказал ее на JLC PCB.

Верхний и нижний слои платы
Верхний и нижний слои платы

Теперь необходимо было запустить все датчики и начать выводить первые данные на светодиоды.

Переходим к написанию кода

Основные сведения о протоколах обмена данными с датчиками я почерпнул в основном из интернета. Измерения проводятся раз в 2 секунды (так как это время измерения самого медленного датчика — DHT11) и суммируются для последующего расчета их среднего значения. Каждые 5 минут обновляется показания светодиодной ленты на основе среднего значения выбранных параметров, затем все измерения  обнуляются, чтобы начать новый 5-ти минутный цикл.

Для перевода количественных показателей качества воздуха в цвет светодиодов, диапазон измерений условно разбил на 3 части (по основным цветам светодиодов, 1-я граница — минимум значения параметра, 2-я граница — оптимальное значение, 3-я граница — максимум): между первой и второй границей для отображения используются только синий и зеленый цвета; между второй и третьей — зеленый и красный соответственно. Если измерение выходит за первую или последнюю границу, то цвет светодиодов назначается синий или красный соответственно, что сигнализирует о чрезмерном уменьшении или превышении некоторого показателя.

void getRGB(int *_red, int *_green, int *_blue, float data, paramsDivideDots divideDots) { volatile float coefficient = (pixels.getBrightness() * 2) / (divideDots.thirdDot - divideDots.firstDot);//коэффициент настройки яркости цвета в зависимости от текущей установленной яркости лампы if ((data < divideDots.secondDot) && (data >= divideDots.firstDot)) {     /* Измерение между 1-й и 2-й границами,      используются синий и зеленый цвета, при приближении,      например, ко 2-й границе цвет становится более зеленым */ *_blue = round(-abs(data - divideDots.firstDot) * coefficient) + MAX_BRIGHTNESS; *_green = round(-abs(data - divideDots.secondDot) * coefficient) + MAX_BRIGHTNESS; *_red = 0; } else if ((data >= divideDots.secondDot) && (data <= divideDots.thirdDot)) {      /* Измерение между 2-й и 3-й границами,      используются зеленый и красный цвета */ *_blue = 0; *_green = round(-abs(data - divideDots.secondDot) * coefficient) + MAX_BRIGHTNESS; *_red = round(-abs(data - divideDots.thirdDot) * coefficient) + MAX_BRIGHTNESS; } else if (data < divideDots.firstDot) {     // Измерение ниже 1-й границы, поэтому цвет устанавливаем синим  *_blue = MAX_BRIGHTNESS; *_green = 0; *_red = 0; } else if (data > divideDots.thirdDot) {     // Измерение выше 3-й границы, поэтому цвет устанавливаем красным *_blue = 0; *_green = 0; *_red = MAX_BRIGHTNESS; } } 

Расчет общего состояния воздуха производил следующим образом:

  1. Если какой-то из параметров воздуха вышел за третью границу, то есть превысил максимум и качество воздуха существенно снизилось, то цвет светодиодов устанавливается только в зависимости от этого параметра;

  2. Иначе, рассчитываем цвета светодиодов для каждого параметра по функции представленной выше, вычисляем среднее значение каждого цвета и устанавливаем эти средние значения на светодиоды.

Выбор именно такого алгоритма обусловлен тем, что для общей оценки качества воздуха нам нужно привести все значения измерений к одной размерности, чтобы можно было вычислить среднее. Лучшей безразмерной величиной для усреднения, чем цвет светодиодов в данном случае не придумаешь.

void WS2812_showParams_standardTotal(float *data) {   // Создаем массив 5x3 (5 - кол-во отображаемых параметров, 3 - кол-во цветов) int colorsArr[DISP_PARAMS_NUM][COLORS_NUM]; for (int i = 0; i < DISP_PARAMS_NUM; i++) {     // Рассчитываем все 3 цвета для каждого отображаемого параметра getRGB(&(colorsArr[i][0]), &(colorsArr[i][1]), &(colorsArr[i][2]), data[i], temp_divideDots); }  int red, green, blue; for (int i = 0; i < DISP_PARAMS_NUM; i++) { red += colorsArr[i][0]; green += colorsArr[i][1];// Рассчитываем средние значения каждого цвета blue += colorsArr[i][2]; } red /= DISP_PARAMS_NUM; green /= DISP_PARAMS_NUM; blue /= DISP_PARAMS_NUM;      // Выводим получившиеся цвета pixels.fill(pixels.Color(red, green, blue), 0, LED_NUM_PIXELS); pixels.show(); delay(100); } 

Код проекта вы можете найти на моем гитхабе.

Итог

На данный момент прототип моей лампы умеет отображать все запланированные показатели состояния воздуха цветом, как по отдельности, так и общее качество воздуха в целом по всем параметрам. Имеется управление с помощью Blynk.

Меню устройства в Blynk
В темной комнате создается мягкое рассеянное освещение, идеальный вариант для ночника
В темной комнате создается мягкое рассеянное освещение, идеальный вариант для ночника

В дальнейшем я планирую

  1. Улучшить нижнюю часть корпуса, закрепить в ней плату;

  2. Заменить вертикальную трубу для светодиодов на прямоугольные платы, с посадочными местами под отдельные светодиоды и разместить светодиоды ближе к краю платы, чтобы они были более отчетливо видны; 

  3. Развернуть веб-сервер, для удаленного управление лампой, который позволит менять режимы отображения параметров, включать одноцветную подсветку и эффекты. На веб-сервере будут отображаться текущие показатели микроклимата дома, графики показателей за несколько дней;

  4. Сделать интеграцию с Яндекс Алисой для голосового управления. С помощью навыка “Домовенок Кузя” Алиса будет отправлять HTTP запросы на веб-сервер ESP-32 и, например, включать ночной режим или выключать лампу. Выбор Алисы обусловлен ее популярностью, поддержкой русского языка и простотой ее навыка;

  5. Убрать датчик озона, так как его точность недостаточна для повседневных наблюдений (+- 10 ppb и диапазон измерений 0-10000 ppb, при том, что норма концентрации в помещении до 60 ppb, а при концентрации свыше 116 ppb в помещении уже находиться нельзя), а цена даже самого популярного датчика высока;

  6. Собрать еще несколько обновленных ламп и отправить их желающим для тестов, с последующим дарением.


ссылка на оригинал статьи https://habr.com/ru/post/647117/

Быстрый, резкий, как пуля, дерзкий. Как работать над перфомансом сайта, чтобы нравиться пользователям и Гуглу

Привет! Меня зовут Андрей Якобчук, я ведущий фронтенд-разработчик в Muse Group. Мы постоянно работаем над ускорением клиентской части наших сайтов. К тому же Гугл с его метриками Core Web Vitals с каждым годом придаёт всё большее значение отзывчивости и стабильности интерфейса сайтов и понижает в ранжировании те, которые считает неудобными для пользователя. В статье я расскажу о том, какие подходы мы используем для измерения и мониторинга перфоманса сайтов, а также дам рекомендации, как можно улучшить ваш проект. 

Зачем ускорять, если всё и так работает

Перфоманс сайта — это та область, где пересекаются интересы пользователя, бизнеса и Гугла. Это первое, что нужно понимать, прежде чем начинать работу над ускорением клиентской части сайта. 

Удобство для пользователя

Важная характеристика интерфейса для пользователя — естественность изменений при взаимодействии с ним. Мы говорим об отзывчивости интерфейса, которая ограничена возможностями восприятия человека. Ещё в 1993 году UX-исследователь Якоб Нильсон в книге Usability Engineering описал, когда человек способен воспринимать конкретные внешние изменения как естественные.

0,1 секунды. Это время, в рамках которого изменение интерфейса воспринимается как мгновенное, а значит, обратная связь не нужна. Сюда можно отнести любые взаимодействия с интерфейсом, которые могут быть обработаны прямо в нём, без взаимодействий с внешними системами, например, без получения данных от сервера.

При клике на кнопку reply мы показываем форму ответа на комментарий. В данном случае нам нужно её просто показать.
При клике на кнопку reply мы показываем форму ответа на комментарий. В данном случае нам нужно её просто показать.

В примере на картинке могут возникнуть проблемы. Например, если основной поток занят другими задачами, задача по показу формы ответа может выйти за 0,1 секунды. Гугл рекомендует вписывать такие взаимодействия в 50 мс, чтобы оставить зазор на случай, если основной поток будет забит другими задачами. 

1 секунда. Это предел для непрерывного потока мыслей пользователя. Даже если он заметит задержку, он не успеет отвлечься. Обычно обратная связь здесь тоже не требуется, но пользователь уже теряет ощущение непрерывной работы с данными и интерфейсом.

Сюда относятся все анимации и более глобальные изменения интерфейса, которые требуют взаимодействия с внешними источниками данных: нам требуется загрузить дополнительный код, чтобы отрисовать часть интерфейса, или обновить что-то в базе данных, чтобы мы могли что-то показать после этого. 

Анимации можно делать 100 мс и меньше, конечно. Но при этом пользователю будет сложно воспринять изменения. Это лишь увеличит когнитивную нагрузку при взаимодействии с интерфейсом. Есть правило: чем больше часть интерфейса, которую мы анимируем, тем более длинная анимация нужна. Например, при hover на кнопку будет достаточно 150 мс, а для анимации показа модального окна уже потребуется 300–500 мс.

10 секунд. Это предел для удержания внимания пользователя. Он может захотеть переключиться на другую задачу. В этом случае важно дать обратную обратную связь: показать, что задача действительно длинная, и пользователь может вернуться к ней позже.

Сюда относятся все глобальные изменения на уровне переходов между экранами приложения или длинные операции, например, загрузка файла в удаленное хранилище. 

16 мс — это важный промежуток времени для анимации и скролла интерфейса. Если каждый фрагмент анимации укладывается в промежуток 16 мс (60 fps), то пользователь воспринимает эту анимацию как плавную. Также важно учитывать, что часть времени уйдет на непосредственную отрисовку кадра, так что на все наши расчеты мы можем потратить до 10 мс. Нас могут сильно ограничивать другие задачи которые выполняются параллельно в нашем коде.

Что можно сделать, если мы не укладываемся в эти рамки

К сожалению, загрузка страницы за 1 секунду при холодном старте приложения — довольно сложная задача, так как общение с сервером вносит свои задержки. По реальным данным время ответа сервера (TTFB) составляет 500–600 мс на десктопе, а на мобильных устройствах, даже при хорошем соединении, может доходить до 1 секунды и более. К тому же оно не всегда одинаково, поэтому Гугл рекомендует укладываться в 2 секунды на хорошем соединении 4G и лучше, а при 3G не зазорным будет уложиться в 5 секунд.

Если изменение происходит в рамках текущей страницы, либо при загрузке страницы мы не укладываемся в 1–2 секунды, то можно показать лоадер в том месте, где появится интерфейс. Более современный способ — показать контентный плейсхолдер на месте UI, который должен подгрузиться. Такой вариант особенно хорош, если блоки интерфейса имеют стандартизированные размеры.

Youtube показывает плейсхолдер вместо UI, пока грузится вся графика, данные и бизнес-логика.
Youtube показывает плейсхолдер вместо UI, пока грузится вся графика, данные и бизнес-логика.

Если же задача выходит за рамки 10 секунд, то можно обыграть ситуацию через прогресс бар.

Прогресс бар при загрузке скора
Прогресс бар при загрузке скора

Хорошая практика — отправить письмо или пуш-уведомления, когда процесс закончится. В примере выше пользователь загружает скор. Он может закрыть страницу, потом вернуться на неё и увидеть состояние загрузки. После того, как его скор будет полностью обработан сервером, пользователь получит письмо, что загрузка завершена.

Такое письмо получает пользователь, когда загрузка скора завершена
Такое письмо получает пользователь, когда загрузка скора завершена

Интересы бизнеса и технические ограничения продукта

Если смотреть на ускорение работы сайта с точки зрения бизнеса, то наша задача — получить результат минимальными усилиями за минимальные вложения. Поэтому мы приняли решение отказаться от SSR. Вся отрисовка сейчас происходит на клиенте. Это позволяет нам:

  1. Держать на 30% меньше серверных мощностей.

  2. Не увеличивать штат разработки на поддержку серверной части отрисовки UI (это хотя и не большая задача, но все же мы должны быть уверены, что и бек и фронт отдают правильную верстку)

  3. Уменьшить технологический зоопарк.

С другой стороны это увеличивает требования к клиентскому коду.

Требования Гугла

Гугл давно уже стоит на страже перфоманс, а после апдейта в августе мы все живем в рамках новых метрик — Core Web Vitals.

  1. Теперь Гугл учитывает не только скорость загрузки сайта, но и то, насколько он отзывчивый и насколько интерфейс стабилен.

  2. Все метрики Гугл собирает с реальных пользователей в реальном времени. Сайт теперь оценивается на основе средней скользящей за последние 28 дней.

  3. Есть четкий performance budget — 70+% заходов по 75-му перцентилю на страницы домена должны быть в зеленой зоне по каждой из метрик (каждая метрика имеет красную, желтую и зеленую зону).

Пользователь, бизнес и Гугл — это три причины заняться ускорением работы клиентской части сайта. Но сначала нужно измерить текущую ситуацию. 

Инструменты аналитики

Здесь я не буду рассказывать про такие стандартные браузерные инструменты, как performance panel в браузерах, об этом уже много писали в различных источниках. Для всех современных фреймворков типа Angular, Vue и UI-библиотек типа React есть свои инструменты разработчика, в которых также можно измерять производительность работы конкретного технического решения. 

В инструментах разработчика Chrome также можно отслеживать Core Web Vitals
В инструментах разработчика Chrome также можно отслеживать Core Web Vitals

Вопрос performance — это, в первую очередь, вопрос баланса. Если не учитывать performance совсем, это негативно повлияет на бизнесовые метрики. Но в то же время — это бездонная бочка, в которую можно вложить бесконечное количество ресурсов. Соблюсти баланс в них нам помогает performance budget. В рамках performance budget мы устанавливаем приемлемые с точки зрения бизнеса SLO для наших перфоманс метрик. Здесь мы также придерживаемся Core Web Vitals, так как с одной стороны, эти метрики охватывают основные моменты отрисовки страницы, а с другой — позволяют нам хорошо индексироваться Гуглом, который является основным источником трафика.

Чтобы понимать, где мы находимся в рамках этого бюджета, необходим мониторинг. В данный момент у нас есть два типа аналитики:

  1. Наша внутренняя аналитика (realtime).

  2. Аналитика построенная на основе Google BigQuery

Realtime аналитика

После релиза наравне с Sentry смотрим дашборд перфоманса. Через 30 минут уже примерно видно, хорошо ли идет релиз. И если заметно, что метрики сильно выросли, то можно принимать решение об откате. Если нет видимого роста, то проверяем релиз через пару часов, чтобы быть уверенными, что все ок.

Данные собираются в ClickHouse, и на их основе мы строим графики в Superset. Данные агрегируем до 5 минут, но они на таком интервале очень шумные. Средствами Superset мы можем укрупнить агрегацию до часов или дней и построить смещение на день или неделю для удобного сравнения. Плюс возможность смотреть по релизам и сразу же определять, что что-то идёт не так. Можно сравнить день со днем или с прошлой неделей.

Здесь видно, что в релизе 1.17.19 что-то пошло не так.
Здесь видно, что в релизе 1.17.19 что-то пошло не так.

Дашборд, где показан общий тренд по дням, смотрим ежедневно.

Core Web Vitals для десктопных скоровых станиц
Core Web Vitals для десктопных скоровых станиц

Для удобства мы прямо на дашбордах установили верхние границы метрик, ниже которых мы считаем, что наш сайт хорошо работает с точки зрения перфоманс. Также видна ситуация относительно прошлых суток и недели, чтобы выявлять аномалии.

Ещё у нас есть свои кастомные метрики, которые помогают при локализации проблем.

Здесь все завязано на то, как наши страницы грузятся. Сначала отрисовывается App Shell — измеряем Layout dom ready. Затем наступает время отрисовки контента страницы — Content dom ready. И лишь после этого случится LCP.
Здесь все завязано на то, как наши страницы грузятся. Сначала отрисовывается App Shell — измеряем Layout dom ready. Затем наступает время отрисовки контента страницы — Content dom ready. И лишь после этого случится LCP.

Про то, что такое App Shell можно почитать здесь

Аналитика Google BigQuery

Этот дашборд достаточно проверять раз в неделю.

По этой аналитике мы смотрим, как нас воспринимает Гугл. Важное отличие — Гугл показывает не абсолютные данные, а скользящее среднее за последние 28 дней. Это значит, что если вы сломали или починили что-то, то абсолютные метрики будут примерно такими же как и в realtime аналитике только через 28 дней. 

Абсолютное значение LCP на мобильной скоровой
Абсолютное значение LCP на мобильной скоровой

Следующий график на дашборде отражает распределение количества загрузок хороших страниц, страниц требующих доработки и плохих. Важно, чтобы загрузок в зелёной зоне (хорошие страницы) было больше 75%.

Google search consоle

C недавнего времени Гугл начал показывать в поисковой консоли качество сервиса с точки зрения перфоманса. Там можно посмотреть общую картину по домену (> 70% — это хорошо).

Процент урлов в зеленой зоне по домену
Процент урлов в зеленой зоне по домену

И указать на конкретные проблемы с сайта.

Провалившись в метрику, можно увидеть уже конкретные URL, которые Гугл считает требующими доработки.

Алерты

У нас есть алерты для перфоманс метрик, которые помогут в случае, если что-то пошло не так, даже если релиза не было. Ну и человеческий фактор никто не отменял. Есть суточные алерты на каждую метрику, а есть алерты за три часа, чтобы отлавливать «жесткие» скачки метрик в негативную сторону и не ждать сутки, чтобы начать решать проблему. 

Почему не Lighthouse и PageSpeed Insights

Мы сознательно перестали фокусироваться на использовании Lighthouse и PageSpeed Insights по двум причинам:

  1. По тепличным метрикам невозможно понять, на сколько стало хуже у пользователей с опытом. Мы агрегируем тысячи значений от реальных пользователей, чтобы получить нормальное распределение в данных без шумов и с хорошей детекцией даже незначительных изменений.

  2. Данные инструменты хороши именно в начале пути, когда только предстоит делать самые базовые оптимизации.

Наконец, настроив сбор данных для аналитики и алерты, можно приступить уже непосредственно к оптимизации.

Оптимизируй это

Здесь я составил небольшой набор рекомендаций, которые помогут поддерживать сайт всегда быстрым.

Фокус на главном

Определите, на какие страницы сайта приходит основной трафик, и сосредоточьте усилия на них. Нет смысла тратить ресурсы на страницы, на которые почти никто не заходит.

Ограничения

Подумайте, какие вещи можно автоматизировать или ограничить, чтобы сайт или приложение были быстрыми «из коробки». Например, для нас такими ограничениями являются:

  1. Ограничения по размеру чанков. Чанк с контентом страницы должен быть всегда один. Также на чанки стоит ограничение по размеру. Превышен размер чанка — деплоя нет.

  2. Ограничения по техническому стеку. Мы очень трепетно относимся к тому, сколько и какие внешние технологические решения мы привносим в продукт. Это важно, чтобы обходиться минимальным количеством решений, особенно это касается первого старта. Любое решение приносится в продукт открыто и только в результате исследования, в том числе сможем ли мы обойтись без этого решения. К слову, общий вес core libs у нас всего 27 КБ gzip.

Оптимизации

Мы фокусируемся на получении наилучшего значения Core Web Vitals как основных метрик производительности фронтенда.

Largest Contentful Paint (LCP) — скорость загрузки основного контента

Для того, чтобы грамотно оптимизировать LCP, необходимо определить, какой элемент интерфейса самый большой, и выстраивать загрузку страницы вокруг него. Чтобы определить какой это элемент или элементы, если их несколько, нужно измерить. Основные моменты по оптимизации хорошо описаны в этой статье, а от меня будет несколько дополнительных рекомендаций.

  1. В месте, где вы управляете состоянием приложения, можно завести свойство, которое будет говорить, когда произошел LCP, и завязать на его изменение отрисовку не критичных с точки зрения первой отрисовки частей UI и non-UI функциональностей (например, аналитики).

  2. Разделяйте код, который отвечает за отрисовку, и код, который отвечает за бизнес-логику. Весь код, который нужен для дальнейшей работы приложения, можно постепенно подгружать уже при взаимодействии пользователя с конкретными частями интерфейса.

  3. Старайтесь не выполнять никакую бизнес-логику до LCP, так как это вызовет выделение лишних процессорных ресурсов.

  4. Также важно понимать, что стабильность UI при его отрисовке также влияет на LCP. Если какие-либо другие элементы будут влиять на позицию вашего LCP-элемента на странице, то это отложит LCP.

  5. Вся below the fold графика должна грузиться через lazy load.

Cumulative Layout Shift (CLS) — совокупное смещение макета

Данный раздел важен только для блоков страницы, которые находятся во viewport либо будут загружены во viewport после взаимодействия пользователя. Важно также понимать, что CLS — метрика кумулятивная, то есть учитываются все прыжки интерфейса, которые были в процессе взаимодействия со страницей. Основные оптимизации можно посмотреть здесь.

Первая отрисовка страницыЕсли есть динамические блоки, то под них обязательно нужно резервировать место под блок.

После взаимодействия пользователя

  1. Вставка новых блоков должна быть в промежутке 500 мс после взаимодействия пользователя, тогда она считается естественной и любой layout shift не будет засчитываться в скор.

  2. Если не получается вставить блок за это время, то необходимо как-то резервировать место под блок.

  3. Если происходит трансформация элемента, например при скролле, то необходимо обязательно использовать CSS Transform для этой цели и анимировать именно через это свойство, так как в этом случае не будет происходить relayout.

Как можно резервировать место

  1. Просто выделить место, возможно, с лоадером.

  2. Делать контентные плейсхолдеры.

Общий совет —  у всех медиа-блоков (embed/video/image) должны быть зафиксированы размеры.

First Input Delay (FID) — время ожидания до первого взаимодействия с контентом

Основные рекомендации по оптимизациям  — в статье. Но, помимо указанного в статье, в негативную сторону на FID может повлиять большое количество одновременных запросов.

Итого

Мы оптимизировали наши основные сервисы, чтобы значения Core Web Vitals для их основных страниц всегда находились в зелёной зоне. Если значения Core Web Vitals ваших сервисов — в жёлтой или красной, вы знаете что делать. Помните, что метрики необходимо постоянно мониторить. К тому же Гугл обещает, что Core Web Vitals будут развиваться и дальше. Расскажите в комментариях, что вам помогает улучшать производительность сервисов. 


ссылка на оригинал статьи https://habr.com/ru/post/647079/

PHP на стероидах: Swoole in production

Представьте себе ситуацию, большой маркетплейс, 60 тыс. посетителей в сутки (600 тыс. просмотров) и это только веб, а с мобильного приложения, плюс еще 100 тыс. уникальных посетителей. С точки зрения HTTP API запросов к PHP бекенду — это порядка 13 млн. запросов (в пиковых нагрузках ~300-400 RPS). И это всё (PHP only) обрабатывает сервер с 8 vCPU (ядрами) и 32 Gb RAM и самое главное, что сервер практически не напрягается (см. КДПВ).

Как это возможно?

Вступление

Статья написана по мотивам продолжения c моей презентации (видео) на конференции PHP fwdays 21 — но уже с более реальным опытом и цифрами по использования Swoole в продакшене. Если эта статья “зайдет” читателям и нужно будет больше полезной информации, сделаю продолжение с ответами на вопросы.

Все мы помним, что PHP был, есть и будет однопоточным языком. Главное, что Swoole extension добавляет в PHP — это конкурентную (практически нативную) асинхронность. Судите сами: сейчас у нас 16 воркеров (PHP процессов), которые обрабатывают 350 запросов в секунду всего на 8 ядрах. И благодаря корутинам, в одном процессе-воркере, в один момент времени, может находиться в обработке несколько разных запросов и каждый в своей корутине. За счет асинхронного IO, который присутствует в каждом запросе (например, запросы к БД), Swoole умеет переключать контекст исполнения PHP кода в другие корутины с другими запросами. Таким образом, мы получаем механизм более плотного использования CPU и возможности реализовать более отзывчивый код. Но вернемся от теории к практике.

Проект

Наш проект — это монолит велосипед на PHP 8, собранный из множества компонентов Mezzio (как скелет), Laminas, Symfony, Doctrine, и других поменьше. Он работает только как (JSON) API бекенд-сервер для разнообразных клиентов (PWA сайт, админка, моб. приложения, микросервисы и т.д). Ну и основные stateful хранилища Postgresql / Redis / Typesense / RabbitMQ конечно же, присутствуют.

Для осознаний масштаба, размер базы данных postgresql >250Гб (с индексами) — это примерно 25 млн. товарных позиций, и более 40 млн. предложений (прайсов) от продавцов, по продажам: ~3500 заказов в день. По нагрузке на БД — это ~2k TPS:

phploc дает такую статистику по размеру кодовой базы:

  • Lines of Code (LOC):             230 648

  • Logical Lines of Code (LLOC): 37 442

Потребление CPU

До Swoole проект жил на стандартной связке Nginx + FPM (PHP 7.4 и на чуть более старых MVC компонентах Zend/Laminas). Для того, чтобы нормально держать трафик (8 FPM инстансов с pm.max_children = 75), необходимы были сервера, с общим количеством в 48 vCPU! Справедливости ради, — это были дешевые ядра. Если говорить в терминологии амазона — t3 тип инстансов, так как они обходилось нам дешевле, чем с2 инстансы, которые имеют более высокую тактовую частоту ядер. Но тесты с c2 показывали, что нагрузку держали бы всего 24 vCPU. В любом случае — это выходит всё равно в 3 раза больше, чем со Swoole сейчас (тут мы уже используем 8 vCPU именно c2 типа). Это первый и очевидный профит, который мы получили.

Потребление памяти

Скептики сразу же спросят, а что же по потреблению памяти (логично, что с новым подходом накладные расходы должны были вырасти)? К сожалению, у нас не осталось замеров потребления памяти до перехода на Swoole (но за счет большого дублирования fpm подов — оно точно не было маленьким в общей сумме). Но как оказалось со Swoole все вышло достаточно не плохо:

В итоге около ~2Gb. Тут учтено полное потребление 2 подов. То есть в каждом поде, отдельный http server — это мастер, менеджер, воркер процессы (8шт), а также сюда включен in memory shared между воркерами кеш (реализованный через Swoole Table).

Вышло, что каждый воркер процесс, примерно, потребляет 80-120Mb, и 200Mb на все остальное.

Простота инфраструктуры

Всего один докер имидж, в котором просто запускается php CLI команда, где и создается высокопроизводительный Swoole http сервер (entrypoint нужен чтобы при запуске настроить некоторые параметры: включить/отключить некоторые php экстеншены или JIT из env переменных переданных докер имиджу).

Dockerfile
Dockerfile

Кстати, размер этого docker image с учетом всего кода (привет vendor папка) всего 120Mb.

Если его запустить, то внутри контейнера будет всего 11 процессов: 1 tini (supervisor)+entrypoint, 1 master процесс, 1 manager процесс и 8 worker процессов.

processes
processes

Само собой, этот же имидж используется для запуска контейнеров с мессадж воркерами для обработки очереди RabbitMQ (мы пользуемся Symfony Messenger компонентом)

Самое главное — настройки http сервера, как и многое другое, теперь под полным контролем разработчиков:

Например, через сколько запросов надо перезапустить воркер процесс. На текущий момент 30к-40к нам хватает на 1 час — нам это подходит для array / object in memory кеша в самих воркерах, чтобы не городить сложную логику с TTL, то есть по сути — это обычные statefull сервисы, которые хранят состояние между запросами.

Connections

А вот попытки использовать (и выиграть при этом) постоянные соеденения (к БД к редису и т.д), реально принесли нам очень много боли. Стандартные подходы и советы, которые дают в этих ваших интернетах, все они выглядили так, чтобы выделить на 1 запрос каждый раз 1 коннект, в конце запроса закрыть, почистить память (особенно это касается Doctrine EnityManager который полностью statefull). Не то, чтобы эти способы были плохие — но в нашем случае это был не вариант без внешних коннекшен пулов, а при таком трафике слишком много создается коннекшенов и слишком большие на них накладные расходы. При этом добавлять сложностей в инфраструктуру не хотелось. Поэтому пришлось написать довольно много оберток для стандартный вещей (типа доктрины, для кешей, который используют редис и т.д.) для того, чтобы использовать и управлять пулом коннекшенов прямо изнутри. В свою очередь, Swoole предоставляет базовый функционал для создания пуллов и использованию каналов (аналог Chan в Go). Не скажу, что это было легко, но только лишь потому, что концептуально, это совсем другой подход и у нас просто небыло достаточно экспертизы.

В случае с доктриной был еще один не приятный момент из-за того, что PDO pgsql, который есть в PHP, сам Swoole не умеет «хукать», то есть превращать нативно этот клиент в асинхронный (pdo mysql не имеет такой проблемы). Вместо этого, он предоставлят собственную обертку-класс для работы с postgresql асинхронно. Соответсвенно нам пришлось писать свой драйвер и к Doctrine.

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

Всегда интересный вопрос в данном контексте. И ответ всегда будет зависит от вашего приложения, от оптимизации SQL запросов (и любого другого IO). Но есть очевидные моменты.

Раньше «бутстрап» нашего аппа занимал более 120мс, то есть самый простой запрос, даже 404 или пустой экшен не мог иметь TTFB меньше 120мс. Теперь тот самый «пустой» запрос занимает цикл диспатчинга в аппе всего 4мс. Это сильно снизило average response time (по сути каждый запрос полегчал на 100мс).

Можно ли было такого добиться на roadrunner? Думаю да, но с некоторыми оговорками. Некоторый выгрыш, например, мы получили тем, что убрали хранение кеша для доктрины из редиса внутрь shared in memory хранилице для всего пода — тем самым снизили накладные расходы на сетевую задержку.

Кроме того, в некоторых моментах мы сумели уменьшить response time за счет паралельных асинхронных запросов (там где один ответ не зависит от другого, например запрос на COUNT при пагинации и сам запрос на результат). В целом мониторинг TTFB говорит нам, что половина (из 35 млн) наших апи запросов (50 перцентиль) происходит быстрее 9 мс:

Выводы

Крайне важный момент: без асинхронных IO клиентов корутины НЕ имеют никакого смысла. Так как IO (по умолчанию в PHP) блокирует сам поток исполнения кода и Swoole просто не может переключить контекст исполнения в другую корутину. 

Так что, если вы не планируете использовать асинхронность на проекте (ваш код не готов к stateless, не нужна экономия CPU, не нужно параллелить IO запросы) — то вам хватит и roadrunner — как минимум, вы получите профит в ”бутстрапинге” вашего аппа.

Полная асинхронность (и использование корутин) в проекте — именно ради этого мы боролись с утечками памяти (спасибо, WeakMap), с доктриной, с разнообразными коннекшенами и их повторными использованием. И всё равно, в течении месяца после выливки в прод, мы отлавливали всякие неприятные ситуации и тюнили разнообразные параметры (которые сперва проставлялись наобум). Как пример: кол-во запросов после которых стоит перестать использовать один и тот же коннект к БД. Выяснилось, что postgresql ой как течёт по памяти, если не пересоздавать соединение (для postgresql это отдельный процесс), даже на простых SELECT-ах — 30к запросов и вот ваша БД уже упала в recovery mode от нехватки памяти…

Для себя я осознал одно: PHP стек закапывать рано. И это я имею ввиду не просто web, а именно в контексте сложных энтерпрайз проектов, которые сейчас так стремятся уйти в модные микросервисы и/или Go (с абсолютно такими же корутинами и производительностью веб-сервера). Поверьте — мы пробовали, в проекте у нас существуют несколько Go микросервисов. Главное, что надо помнить — это соблюдать чистоту кода, не говнокодить, использовать паттерны, современные сторонние решения, DDD, KISS, DRY, YAGNI и куча других страшных слов, поверьте — это не пустые слова и мы в процессе переезда на Swoole в этом не раз убеждались.

To be continued?…

P.S. Для интересующих дать ссылку посмотреть: boodmo.com.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Хотите попробовать Swoole?
8.7% Предпочитаю roadrunner 2
39.13% Интересуюсь, но только как pet-project 9
17.39% Уже запланировал переехать существующим проектом 4
30.43% Хочу попробовать в новом проекте 7
17.39% Никогда — это извращение канонов PHP 4
26.09% Всё сложно… 6
Проголосовали 23 пользователя. Воздержались 10 пользователей.

ссылка на оригинал статьи https://habr.com/ru/post/647077/

Youtube Timestamps — расширение для показа временных меток из комментариев

У YouTube есть возможность оставлять в комментариях временные метки для видео. Просто пишем в комментарии время в формате hh:mm:ss и YouTube сам превратит это в ссылку. Небезызвестный музыкальный сервис Soundcloud позволяет показывать комментарии к трэкам прямо на таймлайне. Так почему бы не сделать такое же в YouTube?!

Так подумал я, а YouTube так не подумал. Благо в браузерах есть механизм расширений и мы можем сделать такое сами.

Расширение в действии
Расширение в действии

В результате получилось расширение YouTube Timestamps (Chrome, Firefox, исходники). Оно загружает 100 топовых комментариев (но не ответов на них) и ищет в них временные метки. Затем отображает их на таймлайне в виде засечек, а по наведению показывает содержимое комментария. Работает и для встроенных видео. Тёмная тема тоже есть.


ссылка на оригинал статьи https://habr.com/ru/post/647081/