Обновить
1

Пользователь

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

Nice write-up! Kudos!

A few comments:

1) the client concurrency limiter has one minor and one major issues. The minor one is that there's a sync.WaitGroup.Go method, which does Add/Done automatically, which would make the code a bit lighter. The major is that the code would create all go routines, but some would be locked by the semaphore. The standard practice is to guard go routines creation by the semaphores. Go routines are usually cheaper than system threads, but they aren't free. There's no need to consume unused resources. Please note: there's no need to create go routine pools either, a common practice is to create a go routine per task as you did

2) you don't need mutexes - go had built in sync/atomics providing all CAS (compare and swap) ops that you need here. Note that in go you rarely need mutexes. Those should be either replaced with channels (of course there are legit mutexes inside) or CAS ops (no mutexes) or x/sync/singleflight package (has a map of semaphores).

And as an extra note - using global variables isn't strictly necessary here. Usual encapsulation would work just great here - a struct with methods. No big changes, but it would look cleaner and would enable concurrent testing.

Очень люблю grpc. Кайфанул от ностальгии. Советую глянуть на connect, который сделан поверх grpc, так что почти не потребует изменений, а так же прогнать код через govet, чтобы почистить устаревшие конструкции. К примеру, API waitgroup и capture счётчика цикла.

Потенциальные улучшения, которые, заодно, ответят на некоторые комментарии: 1) использование chunked upload, чтобы не десериализовать файлы в памяти целиком, а только их кусочки 2) использование простой абстракции для стораджа/репозитория, что позволит легко (почти без изменения кода) пересесть на серверлесс решения или изменить пути и права файлов, если понадобится

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

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

var wg sync.WaitGroup
for range 1e6 {
  wg.Add(1)
  time.AfterFunc(10*time.Second, wg.Done)
}
wg.Wait()

и давайте посмотрим, сколько это займет памяти теперь

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность