LINUX.ORG.RU

Архетипичный Golang

 , , , ,


0

3

Этот пост дает ответ на вопрос: почему Go оптимизирован под конкурентные I/O-нагруженные системы, такие как сетевые сервисы. Пост является квинтэссенцией рассуждений из комментариев в Golang HTTP Middleware: История Go, Goroutines, Инсайт.

Язык программирования это не только синтаксис, но и реализация Runtime. Runtime - это та часть выполняемой программы в которой реализованы структуры данных и алгоритмы поддерживающие синтаксические конструкции языка. А именно реализация словарей, сетов, асинхронности, многозадачности и конкурентности (что не одно и то же).

Golang уникален, а для 2010ых революционен, реализацией связки Синтаксис+Runtime под АРХЕТИПИЧЕСКИЙ дизайн программы. Архетипичная программа на Go - это сервер работающий в одном OS Process на множестве OS Thread, который обрабатывает вал HTTP запросов максимально утилизируя использование OS Threads.

Как известно исполнение алгоритма программы может блокироваться алгоритмически (что-то ждет ответа), а может физически OS Thread ждет IO. В Go оба типа блокировок сведены к минимуму через реализацию прослойки Виртуального Процессора и легковесных Горутин - таким образом переклеивая Виртуальный Процессор между OS Threads, а также тасуя ожидающие и готовые к выполнению Goroutines - реальный CPU практически не простаивает. И весь этот механизм описан простым и понятным синтаксисом.

Таким образом Go спроектирован под написание программ которые в рамках одного OS Process самым оптимальным образом обрабатывают максимально число запросов выше Транспортного Уровня. Архетипический дизайн программы - есть слушающая горутина, она запускает на каждое соединение обрабатывающие горутины. Остальное отдается на откуп Runtime. А Runtime в свою очередь обрабатывает последовательность выполнения горутин на разных Виртуальных Процессорах и разных OS Thread.

// Core of the Architypical Go Application
listener, _ := net.Listen("tcp", ":8080")
for {
    conn, _ := listener.Accept()
    go handle(conn) 
}

Модель планировщика Go называется G/P/M - Goroutine/ProcessorVirtual/MachineThread, или еще по другому N:M, N горутин выполняется на M OS Threads. Иногда ее зову M:N, но я предпочитаю оставлять букву M за OS Threads.

🎆 Суть в одном абзаце от ChatGPT:

Go спроектирован так, чтобы упростить разработку конкурентных I/O-нагруженных систем. Этого достигают за счёт встроенной модели goroutines и runtime-планировщика, который распределяет их выполнение между ограниченным числом OS threads (M:N scheduling). В результате разработчик пишет простой синхронный код, а конкурентность и переключение задач управляются runtime.

И? Какой мы должны сделать вывод из этой простыни?

Ну засунули они грин-треды в кор, и что? Можно подумать, отсутствие этого в коре rust, помешает мне писать код в таком же стиле, подключив tokio

hippi90 ★★★★★
()
Ответ на: комментарий от Nervous

lbvf50txt познаёт мир. Точнее его учётка утекла какому-то искусственному идиоту. Вот он и постит простыни с заумными словами, которые сам не понимает.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от hippi90

Ну засунули они грин-треды в кор, и что? Можно подумать, отсутствие этого в коре rust, помешает мне писать код в таком же стиле, подключив tokio

я чет на жаве задолго до появления GO начал писать, а, оказывается, в мире какая-то революция была…

borisych ★★★★★
()

Если автор ожидал какой-то положительный отклик тут, то это он зря, тут полно хейтеров на все технологии на выбор)

goingUp ★★★★★
()

То ЧТО вы говорите, в целом, верно. Но ТО, что вы это говорите вызывает удивление. Вы явно фанатеете от Go и это в голове не укладывается. Понимаете, вот у порше 911 есть своя фанбаза и это логично. Крутая тачка вызвает эмоции. А вот у лады гранты или рено логана фанатов нет. Потому как «ну, машина, ну ездит». Откуда взяться эмоциональной привязке.

Вот так же и с Go. Отличный язык json’ы перекладывать, но само по себе это занятие скучное. И делать эту работу не так чтоб почётно.

ugoday ★★★★★
()

Таким образом Go спроектирован под написание программ которые в рамках одного OS Process самым оптимальным образом обрабатывают максимально число запросов выше Транспортного Уровня.

Откуда этот бред?

ya-betmen ★★★★★
()
Ответ на: комментарий от hippi90

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

ya-betmen ★★★★★
()

А солярка это в libc умела. Сейчас только оффтопик и DragonflyBSD что-то подобное умеет.

Shadow ★★★★★
()
Ответ на: комментарий от ya-betmen

а чтобы получить дедлок или рейскондишн придется постараться.

Там же автоматическое раскидывание по потокам ОС заявлено. А значит рейскондишн получаешь практически с той же вероятностью, что и при использовании потоков ОС вместо горутин.

И фишка именно в этой автоматике. Можно наплодить сотню тысяч «потоков» и оно не навернёт ОС, как если бы они были потоками ОС, и не будет использовать только одно ядро, как если бы они все были зелёными потоками.

monk ★★★★★
()
Ответ на: комментарий от monk

Там же автоматическое раскидывание по потокам ОС заявлено. А значит рейскондишн получаешь практически с той же вероятностью, что и при использовании потоков ОС вместо горутин.

Да нет, же там отсутствуют средства ручной синхронизации, а вся автоматика сделана так чтобы в это не влететь.

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

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 1)
Ответ на: комментарий от ya-betmen

а вся автоматика сделана так чтобы в это не влететь.

Но как? Сделал два потока, которые читают/пишут в одну переменную. Как Го определит, что их нельзя на разных ядрах запускать?

Иначебы голанг был шустрее платформ с ручным управлением многопоточностью типа жабы.

Так он и есть шустрее. https://github.com/Deeptanshu-sankhwar/Java-Go-Concurrency-Benchmarks

monk ★★★★★
()
Ответ на: комментарий от ugoday

Отличный язык json’ы перекладывать, но само по себе это занятие скучное. И делать эту работу не так чтоб почётно.

  1. Перекладывание JSON’ов — теоретически тоже интересная задача. Есть ведь разные подходы.

  2. Само по себе перекладывание данных есть в любой области и составляет примерно 1% от полезной работы. Чем перекладывание строк в Си авторитетнее перекладывания данных в Go или Java? В обоих случаях более интересна область применения и архитектура.

kaldeon ★☆
()
Ответ на: комментарий от monk

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

Так он и есть шустрее

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

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

Да нет, же там отсутствуют средства ручной синхронизации, а вся автоматика сделана так чтобы в это не влететь.

Ваше высказывание ложно. В Golang есть атомарные операции и есть классические примитивы синхронизации: Мьютексы и Семафоры.

https://pkg.go.dev/sync/atomic

lbvf50txt
() автор топика
Ответ на: комментарий от ya-betmen

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

Race Condtion это алгоритмическая проблема. И от самого его распространенного варианта Lost Update не помогут ни какие синтаксические и Runtime решение Golang.

Смысл Lost Update в том, что общий ресурс конкурирующие акторы затирают устаревшей информацией: Аня и Коля собирают яблоки и пишут результат на доску. Коля запоминает сколько было, добавляет свое и пишет результат на доску. Результаты работы Ани теряются. Это Lost Update.

Переводя на язык Go: горутина может перезаписывать значение переменной в общей области видимости других горутин. Или не правильно реализованный шаблон «single writer» - когда переменную обновляет уже одна горутина, но она сразу перезаписывает полную сумму из канала (total = newValue), вместо добавления дельты (total += delta).

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 2)
Ответ на: комментарий от kaldeon

Перекладывание JSON’ов — теоретически тоже интересная задача.

Бросая в воду камешки, смотри на круги, ими образуемые; иначе такое бросание будет пустою забавою.

Что-то вспомнилось.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Отличный язык json’ы перекладывать, но само по себе это занятие скучное. И делать эту работу не так чтоб почётно.

Почётно/не-почётно и круто/не-круто - это подростковый словарь. Это уже не про языки программирования, это про мироощущение и психологический возраст.

lbvf50txt
() автор топика
Ответ на: комментарий от ya-betmen

Таким образом Go спроектирован под написание программ которые в рамках одного OS Process самым оптимальным образом обрабатывают максимально число запросов выше Транспортного Уровня.

Откуда этот бред?

Докажите обратное. Покажите, что Golang не подходит для обработки множества сетевых подключение в рамках одного OS Процесса.

lbvf50txt
() автор топика
Ответ на: комментарий от monk

Мне понравился ваш ответ. Прочитав его, я написал небольшой очерк про Race Conditions:

Есть расплывчатое определение Race Condition - когда результат зависит от порядка выполнения операций. Это нифигиа не понятно, вот конкретный пример одного из типов Race Condition, который называется Lost Update. Он сразу все ставит на свои места, это не академически не исчерпывающие, но интуитивно и практически достаочное объяснение.

Race condition - это когда конкурирующие (параллельные, асинхронные в данном случае не важно, хоть и это и разные понятия) агенты заполняет общий ресурс устаревшей информацией. Наприме Коля и Аня собирают яблоки, есть общая доска с количеством собраных яблок. Коля запоминает количетсво яблок, добавляет собранные, безцеремонно стирает запись на доске - и пишет свою личную устаревшую сумму. В то время как Аня еще добавила - в итоге вместо Было+СобранноеАней+СобранноеКолей стало Было+СобранноеКолей.

Для решения это задачи должен быть агент превратник, который контролирует результаты работы конкретного агента - Вася который будет примать яблоки от Коли взвешивать и записывать разницу, а потом от Ани. И все это в поряедкеп очереди.

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

В общем Race Condition - алгоритмическая проблема, как правило Lost Update, Превратник Вася - это Акторная Модель или Сериализация доступа еще называется singe writer principle, занятие доски - это Lock и CAS - Compare And Swap.

Но все эти слова - BuzzyWorlds, суть она в том и суть, что кто-то затерает общий ресурс устаревшей информацией.

lbvf50txt
() автор топика
Ответ на: комментарий от lbvf50txt

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

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Потому что когда ты уже вырос, тебе не нужно доказывать это окружающим.

Ну дак и не доказывайте. Не ходите по техническим разделам форума и не рассказываете какая технология почетная и крутая, а какая нет.

lbvf50txt
() автор топика
Ответ на: комментарий от ugoday

Ничего подобного. Попробуй среди десятков способов сериализации выбрать подходящий, ещё чтобы с ORM хорошо дружил. Вопрос явно глубже, чем запрет на функцию strcpy в curl.

Это скучная задача только если бездумно повторять за другими, что само по себе может сделать скучной любую задачу.

kaldeon ★☆
()
Ответ на: комментарий от lbvf50txt

Тебе явно нужно завести блог. По всем постам видно, что он нужен.

CrX ★★★★★
()
Ответ на: комментарий от lbvf50txt

Ну и как я должен тебе что-то доказать если ты свой собственный текст не понял?

ya-betmen ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.