TGViewer
Библиотека Go (Golang) разработчика Библиотека Go (Golang) разработчика @golang_lib · 2.7K subscribers
Post #708 669
🗺️ sync.Map: Почему эта «серебряная пуля» иногда пробивает дно производительности

Как только новичок ловит свою первую панику fatal error: concurrent map writes, он тут же гуглит проблему, находит sync.Map и радостно заменяет все свои словари на него. Казалось бы, идеальное решение из коробки.

Но если вы откроете исходники стандартной библиотеки Go, то увидите, что сами разработчики языка используют sync.Map крайне редко. В 95% случаев обычный map + sync.RWMutex порвет sync.Map по производительности.

Давайте разберем, как эта штука устроена под капотом и почему она может тормозить ваш сервис.

Архитектура двух корзин
Внутри sync.Map лежат не одна, а две мапы:

1. read: Доступна для чтения вообще без блокировок.
2. dirty: Защищена классическим мьютексом.

Когда вы делаете Load(key), Go сначала бежит в read. Если ключ найден - супер, мы прочитали его lock-free.
Но если ключа там нет, Go вынужден брать мьютекс и искать его в dirty мапе. Это называется cache miss. Если промахов становится слишком много, sync.Map принимает тяжелое решение: он берет всю dirty мапу и копирует её в read.

Когда sync.Map - это катастрофа?

• Частая запись новых ключей: Каждый новый ключ попадает в dirty. Это вызывает постоянные промахи при чтении, мьютекс постоянно лочится, а затем происходит дорогое копирование всей мапы. Вы получаете двойной удар по CPU.
• Удаление и перезапись: Стандартный RWMutex справится с этим гораздо эффективнее.

Когда sync.Map - это шедевр? (Два идеальных юзкейса)
Официальная документация выделяет ровно два сценария, где этот тип оправдан:

1. Append-only кэши: Когда записи добавляются один раз и живут вечно (например, кэш скомпилированных регулярных выражений или конфигураций).
2. Disjoint keys (Разделенные ключи): Когда у вас есть 1000 горутин, и каждая читает/пишет строго в свой собственный ключ, никогда не пересекаясь с соседями.

🔥 Senior Tip: Sharded Map (Шардирование)
Что делать, если у вас кэш на 5 миллионов записей, куда постоянно идут конкурентные чтение и запись? RWMutex станет узким местом (будет блокировать всю мапу целиком).
В высоконагруженном проде используют Шардирование. Вы создаете слайс из 256 обычных мап, у каждой из которых свой маленький мьютекс. Хэш от ключа определяет, в какую именно мапу пойдет запрос. Это снижает конкуренцию за лок в 256 раз! (Готовые решения: orcaman/concurrent-map или alphadose/haxmap).

#golang #concurrency #architecture #performance #underhood

📲 Мы в MAX

👉 @golang_lib
More from @golang_lib
  1. Sep 22, 2026🔴AI кодинг интервью с разработчиком из международного FinTech в четверг в 19:00 ДА! Вайбк…
  2. Sep 21, 2026📢 sync.Cond: Как разбудить 10 000 горутин одним вызовом (и не сломать планировщик) Предст…
  3. Sep 17, 2026🔎 pprof: Как найти функцию, которая жрет 80% CPU Сервис на проде внезапно упирается в пол…
  4. Sep 2, 2026☢️ Пакет unsafe: Взламываем систему типов Go Пакет unsafe - это легальный способ сказать к…
  5. Sep 1, 2026🔴 Тестовое собеседование с Go Senior с опытом работы в Яндексе, EPAM и Uzum в этот четвер…
  6. Sep 1, 2026Memory Alignment: Как сэкономить гигабайты RAM, просто поменяв строчки местами Вы написали…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →