Golang Дайджест
8.01K subscribers
44 photos
1 file
171 links
Самое интересное из мира Go: новости, статьи, проекты, сервисы, изменения в языке и др.

Посты публикуются не часто - только самое важное, с чем я лично ознакомился.

Поэтому можно не мьютить канал =)

Обратная связь: @justskiv
Download Telegram
Forwarded from Go Update
🔀 Динамический GOMAXPROCS 🔀

До релиза Go 1.25 осталось около недели, а значит, самое время восполнить пробелы и написать всё то, о чем я (по-хорошему) должен был рассказать в течение последнего полугодия разработки новой версии языка. Начнем с небольшого, но значимого изменения: динамического GOMAXPROCS.

Для тех, кто не в курсе: Go позволяет определить число горутин, которые могут одновременно выполняться в пределах рантайма. Ключевое слово — одновременно. Это значит, что горутин у вас может быть сколько угодно, но выполняться из них (лопатить код, а не находится в ожидании сети, файлов или ответа из сишной либы), в момент времени, будет только число, указанное в GOMAXPROCS. По-хорошему, это число обычно равно числу физических ядер на вашем CPU. Но в серверных окружениях начинаются тонкости, главная из которых, cgroups, является столпом для Docker и K8S.

Смысл вот в чем: в контейнеризированном мире на приложение может быть выделено даже не ядро, а фракция или квота, при этом значения сии могут быть динамическими и изменяться в процессе работы кластера. Процесс может ошибочно исходить из того, что у него есть 64 ядра всего блейда (и как следствие — возможность 64-х активных потоков), но по факту доступных именно нашему процессу ядер намного меньше. И это не вдаваясь в подробности таких вещей, как "привязка к ядрам CPU конкретного процесса" которые актуальны в NUMA окружениях.

До версии Go 1.25 эту проблему частично решала библиотека automaxprocs от Uber, которая выставляла значения наиболее приближенные к ожидаемым оркестратором. Но делала она это только один раз и только на старте. Кроме того, много людей банально не знали об этой тонкости работы рантайма Go и, как следствие, неправильно использовали доступные ресурсы CPU.

Начиная с версии Go 1.25, GOMAXPROCS будет не только выставляться автоматически, но и периодически обновляться в течение жизни приложения, в зависимости от того, как меняется внешнее окружение.

На изменение GOMAXPROCS будут влиять в совокупности три вещи:

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

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

• Вы можете не выставлять в go.mod версию go 1.25.x — обновление придёт к вам только когда вы захотите перейти на поведение языка версии 1.25.
• Вы можете самостоятельно выставить GOMAXPROCS с помощью переменных окружения или с помощью функции GOMAXPROCS. В таком случае автообновление будет выключено, и рантайм доверится вашему суждению.
• Также можно оставить прошлое поведение с помощью GODEBUG переменных containermaxprocs=0 и updatemaxprocs=0.

P.S. Для полноценного мониторинга Go теперь держит в памяти дескриптор доступа к файлам cgroups на время жизни всего процесса.
🔥296👍4
Forwarded from Go Update
🏎️ Об оптимизациях в Go 1.25 🏎️

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

• Цепочка из четырёх 1, 2, 3, 4 PR, суть которых можно описать с помощью одного примера:


var x []int

for i := 0; i < 4; i++ {
x = append(x, i)
}


Если в Go 1.24 и ранее такой код приводил к аллокации в хипе, то начиная с Go 1.25 — нет. А всё просто: make и append теперь, в большинстве случаев, не аллоцируют память в хип до 32 байтов включительно. Вместо этого они используют память на стеке и лишь при превышении объёма начинают идти в хип. Такая вот консервативная оптимизация для слайсов всех типов.

Нулевые значения и "константные" переменные больше не аллоцируют память в хипе при присвоении значения интерфейсу. Продемонстрировать проще всего вот так:


type doubleInt struct{ value1, value2 int }

localVariable := doubleInt{value1: 3, value2: 2}
globalAny = any(localVariable)

localVariable2 := doubleInt{}
globalAny2 = any(localVariable2)


Если ранее подобный код приводил к аллокации, то теперь компилятор достаточно умён, чтобы на этапе компиляции выделить специальное read-only место в памяти и использовать именно его во время исполнения. Особенно приятно, что reflect.Value.IsZero теперь использует сравнение по указателю для нулевых значений структур и массивов, что существенно удешевляет проверку.
👍3715🔥8
Forwarded from Go Update
🎉 Вышел Go 1.25! 🎉

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

♻️ Бинарей в комплекте теперь меньше. Разработчики компилятора активно использовать команду go tool у себя внутри, что убирает необходимость поставлять заготовки в комплекте. Но как минимум go build и go test бинари все еще на месте.

— Новая директива ignore в go.mod. Подробное описание тут. Если в вкратце: для этого вы раньше использовали каталог testdata и каталоги которые начинаются с точки.

— Когда go команда обновляет go 1.xx.y директиву в go.mod она больше не добавляет toolchain директиву.

go vet теперь ругается на неправильное использование sync.WaitGroup.Add и fmt.Sprintf("%s:%d", host, port) ибо есть net.JoinHostPort.

🍵 Новый экспериментальный сборщик мусора. О нем статья будет позже.

🔀️️️️️️ Новый тип runtime/trace.FlightRecorder позволяет записывать только значимые события, а не всё подряд для tracing’га (под капотом используется циклический буфер, который помнит N последних секунд).

🛠 Компилятор теперь генерирует дебаг-инфу в формате DWARF5. Практический итог: бинари едят меньше места и быстрее комбинируются.

🏎️️️️️️ Новый экспериментальный пакет encoding/json/v2. По хорошему про него тоже надо писать отдельную статью, но если в кратце — он намного быстрее того что было внутри encoding/json. А другая хорошая новость заключается в том, что если вы включили GOEXPERIMENT=jsonv2 то больше ничего менять не надо, так как encoding/json сам подключит новую внутряку.

— Тип os.Root приобрел несколько новых методов.

🏎️️️️️️ Функция reflect.TypeAssert позволяет приводить типы из reflect.Value в конкретный тип, минуя потенциально аллоцирующий вызов reflect.Value.Interface.

— Директива GODEBUG=checkfinalizers=1 позволяет понять, как дела в вашей очереди cleanup’ов и finalizer’ов во время каждого GC.

SetDefaultGOMAXPROCS позволяет сбросить настройки GOMAXPROCS если вдруг переменная прилетела через Env или через прошлый вызов GOMAXPROCS.

— Новый метод sync.WaitGroup.Go - больше нет необходимости тащить errgroup если вам не нужен был возврат ошибок и отмена контекста.

🔥testing.T/B/F теперь имеют метод Output() io.Writer который позволяет правильно редиректить вывод внутри вызова теста.

Читать про релиз вот тут.
1🔥40👍218🤯3
Год назад здесь была реклама нового, но уже довольно неплохого курса по API. За год его автор, тимлид команды аналитиков Глеб Учитель, проделал огромную работу: на курс записалось более 1300 человек. И сейчас его знают многие.

Если вы тоже хотите расти по хардам в IT —
добро пожаловать!

Курс стоит всего 13 990 рублей, размещён на платформе Stepik и имеет множество положительных отзывов (отзывы внизу страницы)
————
Начните с бесплатных уроков по архитектуре и интеграциям в чат-боте курса:

@studyit_help_bot

Скидка на курс от канала —
1 000₽ по промокоду TUZOV до конца августа.

#промо #текст_прислан
7🤯6👍54🔥2
Ещё одна статья про Swiss Tables в Go

https://habr.com/ru/companies/oleg-bunin/articles/934906/

Если вам было мало статей на эту тему, то держите ещё один неплохой подробный разбор:

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


#article #swiss_map
👍103🔥3