Как стать автором
Обновить
26
0.1
Александр Дербенёв @alexac

Senior Software Engineer

Отправить сообщение

Мы не дошли до оптимизации сборки кэшами. Команда решила перенять процессы/инструменты у соседней команды, которая начала работу заметно раньше, и вместе с этим притащили базел. Практически сразу я понял, что все кроме меня воспринимают конфигурацию базеля как магию и не понимают, что там происходит. Вся соседняя команда работала на amd64 и им кросс-компиляция нахер не сдалась. А у нас вся команда работает на arm64 и нам бы сборку под две архитектуры поддерживать. А поддерживать такую сложную штуку просто ради того, чтобы она была (потому что опять же никаких плюсов по сравнению с родным тулчейном go), нафиг не надо. Ну и у нас у каждого отдельно взятого микросервиса сборка/тесты проходят меньше чем за минуту. Нам просто нет нужды пытаться это оптимизировать. С базелем без кэшей оно становится втрое дольше, а настраивать кэши базеля для того чтобы решить проблему которую использование базеля и создало...

Кросс-компиляция с CGO это ад даже в самом Go, я недавно заставлял это работать с одним из сервисов.

Я в своем проекте в какой-то момент сделал обратную вещь и выбросил bazel в пользу родного тулинга go/docker и обернул это все мэйкфайлами. По факту, мы поняли, что для нашего проекта bazel не решает ни одной задачи, которые решает родной тулинг. Зато добавляет геморой с поддержкой конфигурации сборки и скорее замедляет сборки (у базеля есть заметный оверхед на настройку тулчейна, который на сборке мелких программ в CI очень заметен). В добавок, мы хотели мультиархитектурные образы на выходе (arm64/amd64), а значит было нужно, чтобы у нас работала нормально кросс-компиляция и создание манифеста в конце. А кросс-компиляция в базеле отвратительно работает.

Зануда мод: UART требует делителя Частот, настройки скорости передачи, настройки наличия и количества старт/стоп битов, настройки проверки на четность, etc. SPI передает тактовый сигнал от мастера к слейву синхронно с данными, с опциональной адресацией слейвов по chip-select, а потому весь интерфейс SPI на слейве состоит из двух сдвиговых регистров и двух регистров буфферов для синхронизации с тактовой частотой контроллера. Самый простой драйвер UART всегда будет сложнее, чем самый простой драйвер SPI-slave.

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

Формат Mach-O достаточно хорошо документирован, а инструменты для работы с ним опенсорсные и кроссплатформенные. Для сборки под macos/ios нужны файлы из SDK, который можно легко вытащить из xcode, но в остальном, если не использовать interface-builder, то ничего не мешает собирать код на других платформах. Если писать на go/rust, это уже работает из коробки, если писать на C/C++/Objective-C/Objective-C++, то с использованием llvm это потребует каких-то усилий на настройку, но в принципе тоже реализуемо.

Плюс есть особые кейсы вроде игровых движков, когда создатель движка собирает код движка в бинарник, а для сборки игры нужно просто сложить вместе бинарники движка и архивы со скриптами и прочими ресурсами. А потом подписать. Например так устроена сборка игр на defold. Инструмент сборки там отлично справляется над тем, чтобы собрать приложение под mac на linux. А вот под ios отказывается, так как хочет работать с подписью.

Есть смысл, на самом деле. C - это lingua franca. Когда нужно дружить друг с другом код на разных языках, зачастую все сводится к предоставлению C-интерфейса. И может быть в имплементации этого интерфейса будет уже C++, go, rust, ассемблере или вообще чем-то экзотичном. Но интерфейс будет на C потому что подцепиться к нему можно из максимально широкого круга языков. Писать весь проект на C, мало кто будет, но какие-то части регулярно получаются написанными на C или хотя бы представляют из себя интерфейсы на C.

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

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

А не лучше в таком случае написать простенький shell скрипт, который будет запускать именно те таски, что вам нужны, вместо того чтобы поддерживать makefile/makesurefile и проверять, что необходимый task runner установлен там, где вы это запускаете?

Я не очень понимаю идею делать отдельную программу таск-раннер. В CI/CD скорее всего понадобится несколько более сложный скрипт, который должен выполнять действия в необходимом порядке. Для запуска сервисов таск-раннеры обычно гораздо более сложные — там либо начинается упаковка в контейнеры, либо много конфигурации про то, как именно софт должен быть запущен, перезапущен, остановлен, etc. (то-есть это уже всякие конфигурационные скрипты для init что-то вроде Procman/supervisord). В сборке нужна полноценная система, отслеживающая зависимости, запускающая команды параллельно, и пересобирающая то, что необходимо, когда необходимо. В обычной работе полезнее сделать так, чтобы необходимые задачи можно было спокойно запускать без вороха дополнительных опций и тогда сложность запуска чего-то вручную или с помощью таск-раннера становится одинаковой.

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

Ninja решает эту проблему тем, что записывает хэш от команды в специальный файлик вместе с другой информацией. Если хеш не совпадает — команда изменилась и надо пересобрать конкретный таргет и то, что от него зависит.

1. Есть довольно известный однострочник, который можно вставить, например в таргет help, для того чтобы полистить таргеты и описать что они делают из комментариев.
2. И это хорошо. Потому что иначе у вас начинаются коллиззии между целями для сборки и вспомогательными целями.
3. Как правило, поставить ; \ в конце строки — не проблема. А во многих случаях это и вовсе не нужно.
4. Небольшой коллапс в синтаксисах makefile/shell, но в целом ничего страшного в этом нет.
5. Настройте себе текстовый редактор. Это никогда не было аргументом ни за, ни против какого-то инструмента.
6. Вот это реальная проблема. Однако многие фичи поддерживаются всеми реализациями, которые вы в здравом уме можете встретить (мы же не говорим о поддержке nmake?), а в большинстве случаев можно достаточно смело делать предположение о том, что будет использоваться исключительно gnu make (да, мне тоже это не нравится).

Гораздо более важной проблемой make, на самом деле является то, что там очень нетривиально сделать так, чтобы изменение команды в Makefile приводило к тому чтобы инвалидировались и пересобирались таргеты, которые собираются этой командой. Ну и производительность так себе. Поэтому все больше и больше вместо make используют связку ninja+генератор (например cmake). Использование отдельного генератора убирает проблемы с совместимостью и синтаксисом, а использование ninja, очень положительно влияет на производительность, решает проблему инвалидации таргетов при модификации команды, а также убирает проблемы совместимости (имплементаций ninja гораздо меньше, и фич там тоже меньше, гораздо сложнее сделать что-то несовместимое).

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

Стоит еще особо отметить, что использовать большинство хуков и тем более каким-нибудь скриптом сборки включать их для всех и каждого — плохая идея. Большинство хуков вызываются не только в тот момент, который ожидает автор хука, но и в еще и большом количестве неочевидных моментов. В гипотетической ситуации, когда кто-то добавляет в pre-commit хук вызов линтера, он практически гарантировано в какой-либо момент ломает кому-нибудь rebase. А если вместо линтера вызывается реформаттер, то это зачастую провоцирует гору конфликтов на каждый коммит затронутый ребэйзом. Ограничения на сообщение еще выглядят разумно, но что-то сложнее туда лучше не запихивать — слишком сложно отловить все моменты, когда это будет стрелять кому-нибудь в ногу.

Блин, этот мем такой баянистый, но почему-то его в последнее время так часто форсят, что аж тошно становится. Имхо, до этого мема в кдпв выглядело лучше.

Мне кажется, автор изначально описал модель, в которой не нужны черри-пики. Если есть feature-бранчи, то и работу надо вести в feature-бранчах, а не в мастере, и потом черри-пикать. Соответственно фиксы делать в релизных бранчах и подмердживать их в мастер, а оттуда уже в фича-бранчи. Получается классический git flow.


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

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


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

type(foo)

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


PEP484 ввел Type hints, которые указывают, что в конкретной переменной ожидаются объекты конкретного типа, но type hints не влияют на то, что происходит в рантайме. Интерпретатор практически полностью их игнорирует. И появились они в языке только в угоду тому, чтобы можно было сделать линтеры вроде mypy, которые их проверяют. Но при этом нет гарантий, что в переменную с type hint будет записан объект тип которого соответствует type hint.

Можно купить в штате, где налог на продажу равен нулю и привезти куда угодно, и возвращать ничего не придется. Только в условиях повсеместных карантинов сложно это сделать. Много есть вариантов. Я вот только сегодня заказал ноут из британского apple store, потому что курс фунта по отношению к евро сейчас упал, а пересылка из UK в Ирландию стоит копейки. ~€150 экономии на пустом месте.

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

1. Цены для штатов указаны в долларах и без налога, так как налог зависит от штата, в котором производится покупка. При оплате к ним добавляется налог, американцы к этому привыкли.
2. Цены для европы указаны в евро, с добавлением пошлины на ввоз и VAT.
3. Цены для россии указаны в рублях, с добавлением пошлины на ввоз и НДС.

Если брать цену в долларах, вручную конвертировать в евро, добавлять пошлины и налоги, то получаются цены из европейского магазина с очень маленькой погрешностью (в пределах 50-80€), что легко объясняется ошибками округления и неправильно выбранными курсами конвертации и декларированной стоимости для расчета пошлин и налогов.

Так что сама компания не берет больше в разных страннах за один и тот же товар. Она просто честно удерживает и уплачивает все пошлины и налоги, установленные в соответствующих странах.
Для iOS 12 все еще регулярно выходят обновления безопасности. Но да, мажорных обновлений больше нет.
Ну уж называть AF_UNIX костылем… Имхо, сейчас это очень недооцененная технология. По факту он:
1. Производительнее любого другого стека, так как ни при каких случаях не покидает пределов хоста.
2. Безопаснее, так как к нему невозможно получить доступ извне. Ни прослушать, ни взломать вас через него не смогут.
3. Имеет встроенное разграничение доступа на уровне fs. Мало иметь доступ к системе, чтобы получить доступ к сокету нужно еще и исполнять код от имени пользователя/группы, которым этот доступ разрешен.

Для любого взаимодействия внутри машины AF_UNIX будет предпочтительнее, чем AF_INET6/AF_INET. Это просто протоколы с разными целями.

Информация

В рейтинге
3 816-й
Дата рождения
Зарегистрирован
Активность

Специализация

Software Developer
Senior
От 100 000 €