Обновить
16K+
30
Иван Щербина@Jester92

Старший инженер-программист (C++/Python)

40,1
Рейтинг
11
Подписчики
Отправить сообщение

Если посмотреть чуть сверху, то у нас есть два подхода:

  • то, что регламентировано спецификациями: PSS, SSS, SSB и прочее. Это можно спокойно описывать, переводя со специфического языка стандартов на человеческий;

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

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

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

В грубом приближении процесс выглядит так:

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

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

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

  4. После этого запускается обратная цепочка PHY. Если всё прошло успешно, получается исходный поток бит, который передаётся выше — в MAC, RLC и остальные уровни стека.

Если совсем упростить, то телефон постоянно отвечает на три вопроса: где сигнал, как он организован и где находятся мои данные.

Спасибо за комментарий.

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

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

Так как сейчас я разрабатываю нисходящие каналы, где одной из основных абстракций является ресурсная сетка и размещение в ней различных каналов и сигналов, именно с неё мне было естественно начать объяснение.

Опорные сигналы, такие как DMRS, безусловно, важны. К ним можно подойти со стороны распространения радиоволн, оценки канала, MIMO и алгоритмов приёма. Но в этой статье я сознательно выбрал другой уровень абстракции — показать, как данные отображаются на время и частоту и как устроена сама ресурсная сетка.

То же касается кодирования и модуляции. За ними стоит огромный пласт теории и инженерных решений: LDPC, Polar, HARQ и многое другое. Это очень интересные темы, но они уже тянут на отдельные статьи.

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

По теме защитного интервала не планировал ничего писать отдельного. Но если вы про частотную составляющую, то его основное предназначение - уменьшать помехи соседним каналам.

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

Имена у нас, конечно, есть. Здесь есть пару хитростей:

  1. Текстовый документ common.txt, в котором часто используемые символы. Их может не быть в текстах, но они могут быть в именах.

  2. Есть fallback на системный шрифт: если нет символа в собранном шрифте, то он берётся из системного. Выглядеть этот символ будет немного не так, как все остальные, но жалоб на это не было.

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

Честно говоря, не рассматривался. Когда добрались до шрифтов, подавляющее большинство было TTF, ещё пару штук OTF. Поэтому естественным образом решили пойти и стандартизировать уже присутствующие на проектах решения и сделать их лучше. Пока что получившийся вариант нас устраивает и по качеству, и по размеру. А задач по улучшению сборки ресурсов всегда много и даже не уверен, что появится время поглядеть на woff2. Но будем иметь в виду куда можно ещё покопать.

В играх изображений на порядок больше. Те проекты, которые сейчас собираю, содержат в районе 50-60 тысяч png-шек. И тоже столкнулись с проблемой места в git, и ограничений в 150/200 Мб на размер приложения. Если кратко по этапам решения:

  1. [git] Обязательно вырезаем мета-информацию. Даже есть прекомитный хук, чтобы в репозиторий в принципе не попадали лишние данные. В некоторых случаях изображение с 25 Мб урезается до 1 Мб. Photoshop любит положить меты с лихвой.

  2. [форматы] Не знаю насколько это актуально для приложений, но у нас для разных платформ сжимается в разные форматы вроде etc2, pvrtc, webp. Это позволяет сильно сокращать размеры.

  3. [сборка] Сборка ассетов выделена в отдельную конфигурацию и собирается отдельно. Плюс обязательно используется кеш (хранится пара: хеш настроек+хеш файла -> итоговый результат). Без кеша сборка около сорока минут, с кешем - пять. Это прямо спасение. В основной сборке в post-build шаге xCode/MS Build запускаем скрипт, который берёт артефакты сборки ассеты и сливает их с другими ресурсами, потом кладёт это уже в нужную папку.

В не игровых приложениях вообще применяются атласы? Они тоже помогают сильно сэкономить и места, и скорость загрузки/отрисовки.

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

Насколько я помню, при ребейз, если нет конфликта, не вызовет pre-commit. А сами проверки вызываются именно в нём. Могу сказать точно про слияния: если в них нет конфликтов и всё слияние прошло автоматически, то проверки точно не запустится. А чтобы наша система на сервере определила наличие хуков у пользователя мы ставим [-] в конце сообщения к коммиту.


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

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


А тесты локально, перед коммитом, спасают сильно: много ломающих изменений чинятся сразу, пока человек максимально в контексте текущей задачи.

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

Сейчас довольно много решений, позволяющих настроить сборку и внедрить туда шаги тестирования. При распределённой команде это будет особенно удобно. Всё же если цель — выпустить проект в мир, то минимальный CI нужен (хотя бы сборка со статическими проверками раз в сутки). Так больше шансов словить косяк не перед дедлайном.
А полноценный CI строится действительно очень долго и небольшими шагами, но жить сейчас без постоянных сборок, рапортующих «Аларма!» в случае сбоя, было бы грустно.
Прошу прощения, но почему статья с текстом «стало актуальна ст. 148 УК РФ», когда последний раз она менялась в июне 2013? Отчего такой интерес вызван? Пытался найти какие-либо законопроекты вносимые, которые меняли бы эту статью как-то, но тоже нет.
Соглашусь в том, что они очень похожи. Если обобщить, то обёртка это доработанный пул объектов с некоторыми ограничениями.
Согласен, в коде всё так же можно допустить ошибку. По поводу Mock-объектов, то для них возможна замена проще, чем переписывать функцию, заполняющую g_storege. Допустим, есть набор глобальных объектов, которые необходимы для реального запуска. Этот же набор дублируется для всех тестов. Данные объекты-дубликаты будут с пустыми реализациями виртуальных методов, чтобы можно было их создать. Есть объект AI, который необходимо заменить на конкретизированный для тестов.
g_storage.RemoveGlobalObject<AI>();
g_storage.AddGlobalObject<AISpecific>();

AISpecific будет выдавать тип AI в методе RecalcHashCode. Поэтому всё хранилище заменять не надо будет. Естественно, остаются сложности с поддержкой двух функций-регистраторов и подобной заменой объектов. Однако в случае с глобальными переменными это уже лучше, чем ничего.
Не совсем. Допустим, у нас есть GameInfo, который содержит информацию об игровых объектах. И есть система AI, которой нужны игровые сущности. В случае глобальных объектов нету уверенности, что сначала создастся GameInfo и AI не будет при создании использовать не инициализированный указатель. В случае с обёрткой вы можете написать
	g_storage.AddGlobalObject<GameInfo>();
	g_storage.AddGlobalObject<AI>();

И уже определённо сначала создастся GameInfo, а потом AI. При удалении будет обратный порядок
	g_storage.RemoveGlobalObject<AI>();
	g_storage.RemoveGlobalObject<GameInfo>();

При таком создании-удалении у AI время жизни меньше, чем у GameInfo, и возможно использование одного глобального объекта другим без боязни получить nullptr.
Хотите эксклюзивный доступ? Забираете (запрашиваете + удаляете) объект из пула и используете сами.

То есть пул не отвечает за уникальность объекта и нужно самому потом следить за этим. Тут и есть проблема. Задача же стояла в том, чтобы заменить именно глобальные объекты, а не все подряд. Чтобы у программиста при использовании не было мыслей про то, что и где он должен проинициализировать или сохранить. В вашем варианте, как минимум, нужно ещё одно место, откуда будет забираться и удаляться объект из пула, а потом доступ к объекту нужно будет совершать через эту сохранённую переменную. В итоге, мы приходим всё к тем же минусам глобальных объектов, что и при использовании оных через extern переменные или синглтоны, но ещё через одну обёртку.
А в случае, если мест использования несколько? Кто тогда отвечает за то, что это место будет одно? Что помешает в пул добавить несколько одинаковых объектов? Ведь данный паттерн будет решать данные вопросы только в случае доработки и введения данных ограничений.
1. За инициализацию объектов отвечает программист. Но так как у вас есть контроль за порядком создания объектов, то это облегчает весь процесс.
2. Если есть объекты, которые зависят друг от друга, то и удалять и регистрировать и удалять их можно в соответствующем порядке. Опять же, в данной обёртке у вас есть контроль за порядком создания и удаления, поэтому избежать обращения одного глобального объекта к другому, когда последний уже удалился, проще.
1

Информация

В рейтинге
204-й
Откуда
Россия
Работает в
Зарегистрирован
Активность