Куда на самом деле уходят токены во время агентного кодинга? ⚡️
Forwarded from Proglib.academy | IT-курсы
В итоге станет понятнее, сколько ресурсов выделять на запуск, когда его останавливать и в какой момент лучше изменить подход🔍
До 31 июля курс можно купить со скидкой, а все материалы останутся в бессрочном доступе.
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱11🤔2⚡1🤩1👾1
В трекере Go появилось предложение #78902 о переносимом SIMD API. Автор — David Chase из команды компилятора. Это второй уровень поверх той работы над SIMD, что описана в проекте #73787. Важно сразу оговорить статус. Это предложение в состоянии Active, оно ещё обсуждается и не принято.
Напомним контекст. В Go 1.26 уже появился экспериментальный пакет
simd/archsimd, который включается через GOEXPERIMENT=simd. Он даёт доступ к SIMD-инструкциям конкретной архитектуры, то есть вы работаете напрямую с типами вроде Float32x8 и должны сами учитывать, что доступно на целевом процессоре. Новое предложение решает другую боль. Писать под каждую архитектуру и под каждую ширину вектора отдельно неудобно, а код получается непереносимым.Идея в том, чтобы дать абстрактный интерфейс к SIMD-векторам, не завязанный ни на архитектуру, ни на длину вектора. Там, где инструкции есть, API работает быстро. Там, где их нет, он сохраняет переносимость за счёт эмуляции. При запуске на разных вариантах одной архитектуры библиотека сама выбирает лучший доступный набор, например переключается между AVX, AVX2 и AVX512.
В первой версии список операций небольшой. Это пересечение SIMD API для wasm и текущего amd64. Набор скромный, зато его проще эмулировать на платформах без SIMD и проще поддержать при добавлении новых архитектур. Типы названы по образцу заглавной буквы и множественного числа, например
Int8s или Float64s. Внутри одного запуска программы все векторы имеют одинаковую длину в битах, поэтому их можно переинтерпретировать методами вида
x.AsFloat64s(). Маски вынесены в отдельную абстракцию, потому что архитектуры реализуют их по-разному. У типов есть методы .Masked(mask) и .Merged(valueIfFalse, mask), а сами маски комбинируются через And и Or.Предусмотрен и спуск на уровень конкретной архитектуры через
ToArch() и обратно через ToSimd(), хотя в прототипе этого пока нет. По задумке это выглядит так://go:build amd64
import (
"simd"
"simd/archsimd"
)
func sum(x simd.Float32s) float32 {
switch a := x.ToArch().(type) {
case archsimd.Float32x8:
a = a.AddPairsGrouped(a)
a = a.AddPairsGrouped(a)
return a.GetLo().GetElem(0) + a.GetHi().GetElem(0)
case archsimd.Float32x16:
// ...
case archsimd.Float32x4:
// ...
}
}
Под капотом код, зависящий от пакета
simd, компилятор размножает на несколько вариантов под разные наборы инструкций, а функции со скрытой зависимостью превращает в диспетчеры. Переписывание идёт рано, чтобы сохранить шанс на инлайнинг. Есть нюанс для инструментов. Сгенерированные имена содержат символ
@ и недоступны из исходного кода, что может влиять на отладчики и утилиты, читающие символы объектных файлов.Есть черновой CL 763100, где сам API лежит в
simd/mocks.go и генерируется автоматически. Пробовать в проде рано, но за направлением стоит следить, если вам важна производительность на горячих циклах.📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤3⚡1👏1💯1
Вопрос с ловушкой прямо в формулировке — и на ней спотыкается половина кандидатов.
Подсказка: прежде чем называть примитив, спросите — а что именно ограничиваем? «Не больше 10 одновременно» и «не больше 100 в секунду» — две разные задачи с разными инструментами. Перепутаете — ответите не на тот вопрос.
Дальше просто: для «одновременно» есть классический примитив, который в Go делается на одном канале особого типа (почему именно такого — тоже любят спросить). А в проде берут готовую обёртку из
golang.org/x/... — тот же механизм, но с ошибками, Wait и отменой через контекст.chan struct{} и что за обёртка — полный разбор📍 Навигация: Вакансии • Задачи • Собесы
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Если вы писали API на дженериках, то наверняка сталкивались с этим ограничением. До Go 1.27 метод не мог объявить собственный параметр типа. Из-за этого операции вроде Map приходилось выносить в функции уровня пакета, а вместо привычных цепочек вызовов использовать отдельные функции.
Особенно это пригодится авторам библиотек, fluent API, builder-паттернов и различных коллекций: операции преобразования можно размещать непосредственно на типе, а не рядом с ним.
⚠️ Но есть важное ограничение. Интерфейсы по-прежнему не могут объявлять методы с параметрами типа, поэтому обобщённый метод нельзя использовать для реализации метода интерфейса. Это осознанное решение авторов Go, а не временное ограничение.
Go 1.27 ожидается в августе 2026 года, а новую возможность уже можно попробовать в Release Candidate
📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥11❤4👾2😍1
Во многих примерах можно увидеть такой код:
db.Find(&users)
Для небольших проектов это работает. Но в production почти всегда стоит выполнять запросы с context.Context.
Если запрос к базе данных зависнет или окажется слишком долгим, Context позволяет отменить его по таймауту или при завершении HTTP-запроса
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
err := db.WithContext(ctx).Find(&users).Error
Если запрос не успеет выполниться за две секунды, драйвер базы данных попытается отменить его, а GORM вернёт ошибку.
func GetUsers(w http.ResponseWriter, r *http.Request) {
var users []User
if err := db.WithContext(r.Context()).Find(&users).Error; err != nil {
// ...
}
}
Если клиент закроет соединение или сервер отменит запрос, операция в базе тоже будет прервана.
Context стоит использовать практически во всех серверных приложениях: HTTP API, gRPC, фоновых задачах и сервисах, работающих с внешними ресурсами
📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱14❤6👍5
Нашли удобную шпаргалку — на одной странице собраны самые востребованные конструкции языка: переменные, функции, структуры, интерфейсы, горутины, каналы, обработка ошибок, методы, указатели и многое другое
📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤1
Утечки горутин — скрытая проблема, которая со временем приводит к росту потребления памяти, деградации производительности и неожиданным падениям. В отличие от «обычных» багов, такие ошибки долго не проявляют себя, а в продакшене отлавливать их уже поздно.
Ниже 5 рабочих приёмов, которые помогут держать горутины под контролем.
1. Мониторинг количества горутин
Запуск фоновой задачи, которая периодически считывает runtime.NumGoroutine() и сравнивает с базовым уровнем — если количество горутин выросло выше порога, сигнализировать (лог, алерт).
go func() {
for range ticker.C {
n := runtime.NumGoroutine()
if n > base+50 { // ваш порог
log.Printf("горутин многовато: %d (base %d)", n, base)
}
}
}()
2. Трассировка с помощью go tool trace
При сложных сценариях запускают трассировку жизненного цикла горутин: когда они создаются, когда завершаются, как взаимодействуют.
func main() {
f, _ := os.Create("trace.out")
defer f.Close()
_ = trace.Start(f)
defer trace.Stop()
for i := 0; i < 10; i++ {
go func() { time.Sleep(500 * time.Millisecond) }()
}
time.Sleep(2 * time.Second)
}
go run . # создаст trace.out
go tool trace trace.out
3. Контекстная отмена
Важно проксировать контекст через цепочку вызовов (например, в HTTP-хендлерах). Когда клиент прерывается или таймаут срабатывает — все дочерние горутины получают сигнал отмены и должны корректно завершаться.
func worker(ctx context.Context, jobs <-chan int) {
for {
select {
case <-ctx.Done():
log.Println("worker: cancelled")
return
case j, ok := <-jobs:
if !ok {
return
}
_ = j // делаем работу
}
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
jobs := make(chan int)
go worker(ctx, jobs)
go func() { // имитация продьюсера
for i := 0; i < 100; i++ {
select {
case <-ctx.Done():
close(jobs)
return
case jobs <- i:
}
}
}()
time.Sleep(3 * time.Second)
}
4. Интеграция goleak в тесты
В тестовой среде использовать goleak.VerifyTestMain или goleak.VerifyNone (внутри тестов) для автоматического обнаружения оставшихся горутин. Это помогает не допустить утечки до продакшена.
func TestMain(m *testing.M) { // глобальная проверка
goleak.VerifyTestMain(m)
}
func TestNoLeaks(t *testing.T) {
defer goleak.VerifyNone(t)
// Демонстрация «правильной» горутины
done := make(chan struct{})
go func() {
time.Sleep(10 * time.Millisecond)
close(done)
}()
<-done
}
5. Graceful shutdown
При завершении сервера или приложения — ждать, пока работающие операции завершатся, использовать таймауты, отслеживать завершение горутин.
Эти паттерны не заменяют внимательного дизайна кода, но дают страховку
📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Займи слот ИТ-Пикником от Т-Банка
8 августа — время отложить ноутбуки и встретиться офлайн на ИТ-Пикнике от Т-Банка в музее-заповеднике «Коломенское». Вот сколько всего запланировано:
— научпоп-лекции;
— мастер-классы;
— дискуссии об ИИ и больших языковых моделях;
— доклады о кибербезопасности;
— примеры, как данные из логов становятся решениями;
— много музыки — Сream Soda, IOWA, LAB Антона Беляева и другие артисты.
Бери с собой друзей, супругов и детей — каждый найдет себе что-то по душе.
Зарегистрироваться и узнать больше можно здесь
8 августа — время отложить ноутбуки и встретиться офлайн на ИТ-Пикнике от Т-Банка в музее-заповеднике «Коломенское». Вот сколько всего запланировано:
— научпоп-лекции;
— мастер-классы;
— дискуссии об ИИ и больших языковых моделях;
— доклады о кибербезопасности;
— примеры, как данные из логов становятся решениями;
— много музыки — Сream Soda, IOWA, LAB Антона Беляева и другие артисты.
Бери с собой друзей, супругов и детей — каждый найдет себе что-то по душе.
Зарегистрироваться и узнать больше можно здесь
👍9