Lasiar работает 💡
161 subscribers
7 photos
47 links
Про Golang и около того

help: @Vallder
Download Telegram
Скорее всего уже на этой неделе будет релиз Go 1.24.
🎉🎉🎉

Об это в прошлый вторник объявила Cherry Mui, которая отвечает за выпуск релизов (и не только).
1.24.0 is planned to be released next week



И создан milestone для 1.25.
🔥4💅31🆒1👾1
Ура, Go 1.24 релизнулся!
🎉🎉🎉

Буквально пару часов делал пост про это https://t.me/LasiarAtWork/42
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👏311👌1💅1
Ранее писал про новую директиву //go:fix inline.

Alan Donovan из Go team недавно сделал PR, в котором добавил в пакеты ioutil и reflect эту директиву для некоторых функций.

Здесь выглядит симпатично, *НО* это сделал инженер из Go team, а какое качество будет у разработчиков сторонних библиотек?

В целом, я буду делать по старинке, через golangci-lint искать deprecated функции и руками буду править.

Как мне кажется, лучше было бы через go vet предупреждение сделать, а не править так исходный код.
5🔥1💅1💘1👾1
Недавно вспоминал о своем докладе: "Почему Docker написан на Go", который я готовил год назад для подлодки.

В этом докладе вас ждет:
- 🕵️ Теория заговора
- 📅 История контейнеризации с 1979 года
- 💔 Почему K8s отказался от Docker (спойлер: не совсем отказался)
- 📑 Не совсем публичные слайды команды dotCloud (ex Docker, inc)

📺 Смотреть

P.S. Все еще актуально, как и год назад! 👀
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥95🥰2
Ранее говорил о GOMAXPROCS и cgroup.

И вот в новой версии Go (1.25) уже не понадобится библиотека github.com/uber-go/automaxprocs, так как cgroup для GOMAXPROCS будет учитываться "из коробки".
Уже даже документация обновлена для master ветки.
🔥1032🍓1💅1
Кстати, про 1.25:
сегодня-завтра должен выйти Go 1.25 RC1
🔥72🍾2💅1
Я пропустил что в Go 1.22 добавили работу с относительно новой сущностью Linux pidfd.

Зачем это в Linux?
Работа с PID по сути всегда гонка:
- Получаем PID процесса (например, PID=100);
- Процесс умирает,
- ОС создает новый процесс, переиспользуя PID=100;
- В итоге мы работаем с совершенно другим процессом.

Это причина уязвимостей: CVE-2019-6133, CVE-2019-15790... А так же причина одного из issue у Go .

Решение
В Linux 5.1 появился системный вызов pidfd_open(pid_t pid, unsigned int flags). Он даёт ссылку на конкретный процесс, а не на PID, который может быть переиспользован.
Дальше (вплоть до ядра 6.5) добавили и другие методы получения pidfd.

Что в Go?
И уже в Go 1.23 в методах и функциях, которые относятся к процессу используется по возможности pidfd.
🔥9👍4🍾2👨‍💻2😁1💅1
В последнее время довольно часто приходится работать напрямую с TCP/UDP, а иногда и по SSH.

В таких случаях особенно важно использовать connection pool и следить, чтобы соединение не "умерло" - - так мы избегаем накладных расходов на рукопожатие (особенно важно если в протоколе есть дополнительные "телодвижения").

Отлично в этом помогает библиотека от jackc -- puddle (автор, кстати, того же pgx).

Грубо говоря, это sync.Pool{}, только не для памяти, а для ресурсов, причём с возможностью ограничить количество создаваемых экземпляров. Если лимит достигнут, попытка получить новый ресурс блокируется до появления свободного -- что помогает контролировать нагрузку и избегать перерасхода соединений.

Примеры использования вне README можно посмотреть в исходниках pgx (файл pgxpool/pool.go) и ch-go (файл chpool/conn.go).

Ну и небольшой пример из README:

func main() {
constructor := func(context.Context) (net.Conn, error) {
return net.Dial("tcp", "127.0.0.1:8080")
}
destructor := func(value net.Conn) {
value.Close()
}
maxPoolSize := int32(10)

pool, err := puddle.NewPool(&puddle.Config[net.Conn]{Constructor: constructor, Destructor: destructor, MaxSize: maxPoolSize})
if err != nil {
log.Fatal(err)
}

// Acquire resource from the pool.
res, err := pool.Acquire(context.Background())
if err != nil {
log.Fatal(err)
}

// Use resource.
_, err = res.Value().Write([]byte{1})
if err != nil {
log.Fatal(err)
}

// Release when done.
res.Release()
}
👍9🔥7
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Уххх!
В Go начали завозить intrinsics для SIMD.

То есть, возможно, можно будет вызывать SIMD инструкции напрямую, прямо из Go кода.

Для теста можно подтянуть ветку через gotip:
go install golang.org/dl/gotip@latest  # если ещё не установлено
gotip download dev.simd # собираем ветку dev.simd


Правда, пока что поддержка только для amd64, так что локально потыкать у меня не получится :(

Как только появится arm -- обязательно сделаю бенчмарки и поделюсь результатами.

Кратко о текущем состоянии -- в комментарии Cherry Mui: https://github.com/golang/go/issues/73787#issuecomment-3208178910
🔥31👏1🍓1💅1👾1
Всем привет!)

Второй год участвую в программном комитете конференции E-CODE, помогаю с формированием трека backend.

Буду лично на мероприятии, оно пройдёт 13-14 сентября.

Если вы тоже там будете -- можно пообщаться в перерывах между докладами)
6🥰4🐳1🍓1👾1
В Go завезли поддержку valgrind -- утилиты, которая может обнаруживать утечки памяти.

Это, конечно, круто, но зачем?

На этот вопрос ответил автор CL, а также security team lead в Golang -- Roland Bracewell Shoemaker.

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

Тут у кого-то может возникнуть вопрос:
Зачем нам функции, которые работают за константное время? Разве мы не хотим, чтобы они выполнялись как можно быстрее?
А тут стоит посмотреть на роль того, кто добавил CL SECURITY team lead.

В криптографии очень важно, чтобы функции выполнялись за константное время.
Если передавать разные входные данные и замерять время выполнения, можно провести timing oracle attack.

Тривиальный и упрощённый пример:
Мы побайтово сравниваем два хеша и при первом несовпадении выходим из функции раньше.

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

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

Для проверки этого как раз и нужен valgrind -- он отслеживает, какие области памяти и регистры используются в каждой ветке исполнения.

Подробнее про использование valgrind в рамках поиска функции, которые выполняются не за константное время можно почитать тут репозиторию аж 15 лет.
🔥93👾2💅1
TL;DR
Изменения пользователя и прав в Dockerfile при копировании можно выполнить одной командой.

COPY [--chown=<user>:<group>] [--chmod=<perms> ...] <src> ... <dest>


Docker использует файловые системы, c поддержкой Union mount -- накладывание одного дерева файлов на другой.

Одно такое дерево файлов в терминологии Docker называется слой (layer).
Слои нельзя изменить, изменения записываются в новый слой.

Каждая инструкция в Dockerfile создает отдельный слой.

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

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

Чтобы избежать этого можно сразу указать --chown и/или
--chmod при копировании.


┌─────────────────────────┐
│ Верхний слой │ ← Изменения прав (chmod/chown)
├─────────────────────────┤
│ Данные приложения │ ← COPY . /app
├─────────────────────────┤
│ Базовый образ (OS) │ ← FROM ubuntu/alpine/etc
└─────────────────────────┘
6👍3🥰2👾21💅1
Потихоньку в стандартную библиотеку Go добавляют работу с generic.

В Go 1.26 добавили функцию errors.AsType[E error](err error) (E, bool).

Релиз Go 1.18, где появились generic был 25 марта 2022 года, а уже через 10 дней появился issue, где предлагалось добавить generic функцию в пакет errors.
Только первоначально говорилось об изменении errors.As(), возможно из-за этого только спустя три года добавилась функция errors.AsType().

В целом -- мне нравится.

Во-первых, это выглядит симпатично:

pathError, ok := errors.AsType[*fs.PathError](err)


Во-вторых, это значительно быстрее:
Код бенчмарка: https://go.dev/play/p/AcQyInSlR7D
Результат:

goos: darwin
goarch: arm64
pkg: test
cpu: Apple M4 Pro
│ as.txt │ as_type.txt │
│ sec/op │ sec/op vs base │
Errors-12 33.480n ± 1% 2.113n ± 1% -93.69% (p=0.000 n=20)

│ as.txt │ as_type.txt │
│ B/op │ B/op vs base │
Errors-12 8.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=20)

│ as.txt │ as_type.txt │
│ allocs/op │ allocs/op vs base │
Errors-12 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=20)
🔥43💘2👍1💅1
https://t.me/LasiarAtWork/53

В Go 1.26 добавят реализацию SIMD для amd64.

При этом возможно этот пакет будет использоваться в green tea (новый GC, который будет включен по умолчанию в Go 1.26), что должно ускорить добавление других архитектур в пакете simd.
🔥5
Там Nvidia в ядре Linux готовят сетевую подсистему под 1600Gbps (8x200Gbps).

Скорость просто невероятная!

Думаю что это необоходимо для нейроных сетей.

Немного контекста:
Nvidia с 2020 года владеет компанией Mellanox, которая выпускает сетевое оборудование для HPC.
🔥42
Неожиданно для себя я узнал что в DNS можно передавать порт 🙂


Всё благодаря новому типу записи -- SVCB который появился пару лет назад и описан в RFC 9460.
Вообще в драфте он был достаточно давно, даже некоторые DNS клиенты/сервера уже реализовать начали опираясь на драфт.

Во-первых у нас не совем типичные запросы:
мы хотим обратиться к "foo://api.example.com:8443", из-за этого у нас должен быть запрос:
_8443._foo.api.example.com

Во-вторых можно передавать дополнительную информацию:
Я локально поднял DNS сервер и указал там SVCB запись.

запрос:

kdig _443._https.svc.example.test @127.0.0.1


ответ:

;; ANSWER SECTION:
_443._https.svc.example.com. 3600 IN SVCB 1 . alpn="h2,http/1.1" port=8443 ipv4hint=192.168.0.42 ipv6hint=fe80::1805:8978:a257:cea7


Можно так же заметить что передает не только порт, но:
- alpn Application-Layer Protocol Negotiation -- инфомрация про протоколы, чтоб сразу понимать по какому протоколу стоит подключиться;
- ipv4hint, ipv6hint -- ранее нужно было выполнить два DNS запроса A для IPv4 и AAAA для IPv6, а сейчас всё можно получить за один раз.

В целом DNS становится сложнее, но при этом -- мощнее.
С помощью SVCB можно экономить на RTT. Кажется, это действительно крутая штука.
👍6🔥42
В Steam вышла игра NebuLeet.

И, казалось бы, зачем это я пишу в техническом канале?
А дело в том, что разработчик -- Iskander (он же quasilyte), а игра написана на Golang!

Да, именно на Go -- не только гонять JSON с базы на фронт, K8s, Docker, но и геймдев.
🔥71👍1💅1🦄1👾1
в 1.26 кроме green tea есть еще интересная оптимизация связанная со слайсами:
stack-allocation optimization
for the backing store of slices.


В чем суть этой оптимизации:
В некоторых случаях аллоцировать слайс во время append(а) на стеке, а не в куче. Это снижает нагрузку на GC.

К примеру, типичный код:

func f(n int) []int {
var r []int
for i := range n {
r = append(r, i)
}

return r
}


Во время итерирования, когда возрастает capacity (1, 2, 4, 8... итерация) создается память, которая не нужна. Эта памяти будет зачищаться при работе GC.

И в связи с этим стараемся не нагружать GC, а аллоцировать эти мусорные объекты на стеке.

И уже перед выходом из функции помещаем слайс на heap.

func f(n int) []int {
var r []int
for i := range n {
r = append(r, i)
}

r = move2heap(r) // Подставляется во время комплияции
return r
}


Немного деталей:
Во время append(а) вызывается не growslice, а growsliceBuf, где буффер это поинтер на стэк (link).
Перечень того, где может использоваться эта оптимизация перечислина в тестовом файле, (где указано growsliceNoAlias, growsliceBuf).

Links:
CL: go-review.googlesource.com
Более подробная информация как это работат: cmd/compile/internal/slice/slice.go
👍5🔥3👏2