Она для программистов на других языках, которым инетересно, стоит ли тратить время на go.
Чем отличается go, например, от java и чем может быть полезен.
Принципы go
Когда-то можно было просто взять и создать новый язык программирования.
Сейчас язык имеет шанс занять какое-то место только если у него есть четкие принципы, которым следуют его создатели. Другими словами — собственное лицо.
Принципы go — это простота и продуктивность.
Принцип простоты звучит так:
Если без чего-то можно обойтись, без этого нужно обойтись.
Принцип продуктивности:
Самое ценное — это время, затрачиваемое разработчиком. Его надо минимизировать всеми доступными способами.
Проиллюстрирую принцип простоты:
В go очень мало языковых конструкций. Например, только один цикл. Go можно выучить за два вечера.
В go отказались от динамической загрузки библиотек — результат компиляции один большой исполняемый файл
В go нет warning-ов при компиляции. Любая некорректность или «многословие» — это ошибка компиляции.
В go встроен автоформат кода на уровне самого языка. Есть только один каноничный вид кода на go.
Теперь несколько примеров продуктивности:
Код на go на 20-30 процентов короче аналогичного на яве (там просто не лишних слов, например, нет точки с запятой в конце каждого предложения, нет круглых скобок в операторах условия или цикла etc).
В go очень быстрый компилятор (несколько секунд на компиляцию большого проекта).
Продуктивности служит не только сам язык, но и стандартные инструменты с ним поставляемые.
Инструменты повышения производительности
Профилировщики
начну с небольшого отступления о том как я, программист java, пришел к использованию go.
Я делал игровой проект — многопользовательский космический шутер.
Изначально я написал серверную часть на java. Она работала.
Но очень быстро все уперлось в производительность.
На одном сервере можно было запустить не более 300 клиентов.
Это слишком мало, чтобы игра стала рентабельной.
Что я мог сделать с этим, как программист java?
На самом деле немногое:
1) Используя метод пристального взгляда искать в коде неэффективные места, пробовать их исправлять и, после каждого изменения, вновь запускать нагрузочные тесты. Этот способ очевидно неэффективен.
2) Погрузиться в изучение альтернативных серверных библиотек, пробовать разные варианты. Это тоже не дает никаких гарантий — возможно проблемы в моём собственном коде, или вообще в самом языке java.
3) Наконец, я мог купить один или несколько платных профилировщиков и попробовать получить какую-то информацию от них. Но и тут есть проблемы. Если использовать локальный сервер, стоящий у нас в офисе, я не мог создать нужной нагрузки, поскольку у нас в офисе нет нужного количества свободных машин, чтобы запустить несколько тысяч клиентов. Если же использовать внешний сервер, то требовалась довольно сложная конфигурация, чтобы запустить там профилировщик. Наконец, выбор профилировщика сам по себе является нетривиальной задачей.
В go эта проблема решена очень удобно.
Профилировщик там является частью языка.
Включить его можно на любом сервере, а результатом его работы является файл, который можно скачать на свою машину и не спеша изучить при помощи очень удобных инструментов.
Эти инструменты покажут какие именно строчки кода тратят более всего памяти и процессорных циклов.
Их использование дает возможность быстро и эффективно найти и исправить все проблемные места. (Которые, кстати, почти всегда оказываются не там, где ожидаешь их найти.)
В моем проекте сервер, переписанный на go изначально «тянул» только 20 клиентов (много хуже, чем на яве). После работы с профилировщиками эта цифра выросла до 2500.
Race detector
Другая головная боль всех писателей многопоточных приложений — race conditions.
Это такие трудноуловимые баги, которые возникают только если звезды сошлись определенным образом. То есть, если потоки запустились в одном порядке, баг есть, если в другом — нет. А порядок непредсказуем.
В go для решения этой проблемы есть стандартный инструмент — race detector. Если его включить, программа на go будет писать в лог обо всех небезопасных обращениях к общей памяти из разных потоков.
Используя race detector можно быстро, целенаправленно найти и устранить все проблемные места.
Интересные конструкции
Я не имею целью научить программировать на go и не стану разбирать все его конструкции. Хочу остановиться только на трех, наиболее интересных. Все они описывают парадигмы, которых в яве в чистом виде нет. И эти парадигмы очень полезны.
Это интерфейсы, горутины и каналы.
Интерфейсы
Интерфейс в go похож на интерфейс в яве или c#. Это — набор сигнатур методов, но без реализаций.
Основная разница в том, что go не требует объявлять, что какая-то сущность имплементирует какой-то интерфейс.
Достаточно, чтобы у сущности просто были все нужные методы.
Что это даёт? Decoupling.
Вы можете взять чужую библиотеку. Найти там сущность с каким-то набором методов, создать у себя интерфейс с тем же набором и использовать эту сущность, как этот интерфейс. Вам не надо изменять чужой код, не надо завязывать свой код на чужие сущности и не надо писать адаптеров, которые являются классическим boilerplate кодом. Еще одна иллюстрация принципа продуктивности.
Горутины
Сначала для многозадачных приложений в языках программирования были придуманы процессы. Они были тяжеловесными, имели собственное адресное пространство и быстро «жрали» ресурсы системы. Потом появились треды (или нитки). Они были гораздо легче и работали в одном адресном пространстве. Если процессов обычно запускали единицы или десятки, то тредов можно было иметь уже сотни. Однако при неаккуратном использовании и они могли отнять все ресурсы системы. Каждый тред всё-таки занимал какие-то ресурсы, даже если был заблокирован.
Чтобы ограничить число тредов, начали использовать тред пулы.
Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом. В Go горутины крайне дешевы. Вы можете запустить миллионы горутин без проблем для производительности. Единственное требование — горутины должны быть «маленькие». То есть горутина должна быстро сделать свою работу и либо выйти, либо заблокироваться (что с точки зрения планировщика горутин одно и тоже).
Каналы
Каналы являются расово правильным средством коммуникаций между горутинами.
В go есть важное правило:
Don't communicate by shared state. Share state by communication.
Его смысл — не пользуйтесь переменными, к которым имеет доступ более одной горутины.
Вместо этого заставьте горутины пересылать данные друг другу.
Эта пересылка данных как раз и делается через каналы.
Канал в go это очередь (буфер) в один конец которого можно писать, а из другого читать.
При этом, горутина блокируется при попытке писать в переполненный канал или читать из пустого канала.
Но самое интересное — go имеет конструкцию для одновременного чтения из нескольких каналов.
Горутина может перечислить несколько каналов, на которых она будет сидеть и ждать появления сообщения в одном из них. Получив это сообщение, горутина разблокируется, обрабатывает его и (обычно) снова ждет следующего сообщения.
Так, например, в чат сервере горутина может ждать как сообщение от пользователя так и сигнала о выходе из чата. Одновременно.
Управление зависимостями
Такие инструменты управления зависимостями, как maven или gradle сегодня существуют для всех серьезных языков.
В go пошли дальше и сделали поддержку управления зависимостями на уровне самого языка.
При импорте пакета (конструкцией, аналогичной import в яве) можно указать как локальное имя, так и адрес пакета в любой современной системе контроля версий (например, в git).
Например, «github.com/gorilla/websocket»
Go самостоятельно скачает нужный пакет и включит его в ваш проект. Если какой-то пакет уже был ранее скачан, то он просто будет использован. Вы также можете попросить go обновить все пакеты до их последних версий.
Здесь, впрочем есть один неприятный момент — go всегда скачивает последнюю версию пакета. Если над проектом работает несколько человек, это может привести к различным версиям пакетов у разных разработчиков.
Для решения этой проблемы используются внешние инструменты — менеджеры пакетов.
Один из лучших на сегодняшний день — glide.
В основе glide – два действия:
1) Найти все зависимости проекта, и записать их в файл
2) Cкачать эти зависимости
При этом файл можно редактировать вручную, указывая, при необходимости, другие версии пакетов (отличные от последней).
В качестве идентификатора версии в GIT используется идентификатор коммита (в других системах контроля версий используются специфичные для них идентификаторы).
Слабые стороны go
Любой принцип имеет не только сильные стороны, но и слабые.
В go, на мой взгляд, есть одна плохая и одна ужасная вещь, которые проистекают из принципа простоты.
Плохая — это отсутствие generic-ов. Ужасная — обработка ошибок путем проверки возвращаемого функцией кода.
Без generic-ов приходится отказываться от строгой типизации.
А обработка ошибок приводит к большому количеству однотипного кода. Который, к тому же, можно вовсе забыть написать и оставить ошибку необработанной.
Кроме этого, следуя принципу продуктивности, было решено ввести в go garbage collector. Само по себе это неплохо. Но важно понимать, что этот самый коллектор будет запускаться каждые несколько секунд и заметно притормаживать систему. С этим, впрочем, можно успешно бороться.
Выводы
Стоит ли ява программисту полностью переходить на go? Нет. Во всяком случае, пока. Ява в среднем быстрее. В ней больше полезных библиотек и наработанных способов создания приложений.
Стоит ли использовать go для решения определенных задач? Однозначно, стоит.
Какие задачи лучше всего решать на go? Создание многопоточных высоконагруженных серверных решений, в которых потоки много коммуницируют между собой.
Какой язык лучше учить новичку — go или яву? Однозначного ответа нет, но со временем аргументов в пользу go будет все больше.
Возраст языка играет роль. Более старый язык обрастает «историческими» вещами. Что-то было добавлено давно, теперь никому не нужно, но выбросить нельзя, поскольку нарушится обратная совместимость.
Какие-то конструкции языка или стандартных библиотек, ранее актуальные, сейчас выглядят неуместно, кажется, логичнее делать эти невостребованные вещи вне стандарта языка.
Для каких-то стандартных проблем накопилось множество альтернативных решений разного качества. Для новичка всё это — большое количество бесполезных но необходимых знаний в стиле: «Здесь нужно быть особенно осторожным. Здесь у нас ЛУЖА».
Go создавался гораздо позже и на сегодня в нем присутствует все, что востребовано сейчас и ничего лишнего.
Комментарии (270)
esinev
29.07.2016 23:33+20В java тоже есть интрумент для анализа производительности и поиска узких мест — Java Mission Control.
Он идет в составе JVM.
Причем он при его использовании производительность практически не падает (от 1 до 5%).
Включается несколькими параметрами:
-Dcom.sun.management.jmxremote.rmi.port=7091 -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -XX:+UnlockCommercialFeatures -XX:+FlightRecorder
Дальше можно зайти на сервер по ssh с перенаправлением портов:
ssh user@host -L7091:127.0.0.1:7091
Запускаем jmc и подключаемся к 127.0.0.1:7091
Вместо goroutines можно использовать fibers http://docs.paralleluniverse.co/quasar/
softaria
29.07.2016 23:41-2Спасибо. Не знал про Java Mission Control. Обязательно попробую.
Что касается quasar, я сравнивал сами языки, а не экосистему.AlexTheLost
30.07.2016 08:34+27Без обид, но факт что вы не знаете про инструменты анализа производительности JVM, и как видно не удосужились поискать о них информацию говорит не в пользу вашего профессионализма. Но вы все же беретесь сравнивать платформы, а ведь ваш пост будут читать и за счёт авторетета хабра будут рассматривать ваше мнение так же как авторитетное.
По мимо этого. Я вижу что написание кода на go в лоб, без профилирования не дало высоких показателей(50 человек онлайн) и только после устранения узких мест был рост до 2500. Возможно на java результат будет не хуже?
Вы говорите об эффективном параллельной обработке данных на go за счёт мощных встроенных средств. Но JVM в своём арсенале уже содержит множество библиотек и Фреймворков, таких как приведено выше и даже более распространённых и проверенных, как Akka. Акторная модель скорее всего решит ваши проблемы многопоточности, не заставляя радикально менять платформу, а такой сервер как netty или модуль akkaHttp проблемы с масштабированием кол-ва соединений.softaria
30.07.2016 08:41-17Как раз про это я и написал.
Чтобы сделать это на java мне надо было:
1) Удосужиться поискать информацию (VisualVM? YourKit? Java Mission Control, который был добавлен, начиная с java 7 и, как тут заметили, платный).
2) Попробовать каждый из них.
Вы видели, например, VisualVM? По сравнению с инструментами, предлагаемыми go, это — прошлый век.
3) Далее, я бы обнаружил, что проблемы есть не только в моём коде, но и в серверной библиотеке.
Что взять? Jetty, Netty, а может VertX или Play?
Опять масса проб и ошибок.
Мысль не в том, что на java нельзя сделать сервер быстрее.
Мысль в том, что на go для этого потребуется намного меньше времени.Optik
30.07.2016 09:31+23Ваши пункты намекают, что ваши знания java возможно даже хуже чем знания go.
Suvitruf
30.07.2016 10:53+12Выглядит как «я не хочу разбираться и выбирать необходимый инструмент для Java проекта, поэтому возьму мейнстримный Go».
softaria
30.07.2016 11:31-11Я хотел сравнить трудозатраты на решение одной и той же задачи в java и в go.
В go они существенно меньше для этой задачи.
Source
30.07.2016 11:44+9Когда в Go дело доходит до использования сторонних библиотек, то ситуация становится гораздо печальнее, чем в Java. Куча библиотек, которые делают примерно одно и то же, приходится реально вчитываться в код каждой, чтобы сделать адекватный выбор.
Да что там библиотеки… Попробуйте для начала веб-фреймфорк выбрать: awesome-go#web-frameworksFireGM
30.07.2016 19:04-4Iris же. Можно делать очень быстрые микросервисы, но можно и подобие монструозного django.
iqiaqqivik
31.07.2016 18:42+1Фраза «эта прекрасная машина умеет варить суп, жарить мясо и печь пироги» в 102% случаев означает, что все вышеперечисленное эта машина делает отвратительно.
Suvitruf
01.08.2016 09:23-1<sarcasm>Если только под машиной не подразумевается жена</sarcasm>.
valery1707
01.08.2016 12:48+5Что взять? Jetty, Netty, а может VertX или Play?
Как можно всё это свалить в одну кучу и при этом делать вид что разбираетесь в Java?
- Jetty — эффективный контейнер сервлетов. Да у него довольно эффективный IO, но его основное назначение это именно контейнер сервлетов
- Netty — фреймворк для эффективного сетевого IO.
- VertX — фреймворк для написания эффективных сетевых приложений. Собственно для эффективного IO использует Netty
- Play — полноценный веб-фреймворк, которому для работы нужен контейнер сервлетов
Да даже просто причитать описание проектов на вики хватило бы что бы выбрать нужный.
grossws
30.07.2016 02:44+3Стоит добавить, что для использования JMC и Flight Recorder на приложении в production'е необходимо иметь специальную лицензию от Oracle (Java SE Advanced/Java SE Suite), как и для остальных Commercial Features. Насколько я понял из BCLA, использоваться для разработки её вполне можно.
Randl
29.07.2016 23:56+15В go очень мало языковых конструкций. Например, только один цикл. Go можно выучить за два вечера.
Это скорее не простота, а минималистичность. Мне нравится минималистичность, но с ней важно не переборщить (крайний пример — брейнфак. хотя нет, крайний — boolfuck). С учетом повсеместного интернета, когда достачно помнить, что что-то сделать можно, а гугл подскажет как — переборщить очень просто.
В go отказались от динамической загрузки библиотек — результат компиляции один большой исполняемый файл
Какие у этого плюсы?
В go нет warning-ов при компиляции. Любая некорректность или «многословие» — это ошибка компиляции.
Каждый раз когда вместо простого и понятного хака приходится писать функцию на полэкрана, умирает один котенок.
В go встроен автоформат кода на уровне самого языка. Есть только один каноничный вид кода на go
И не дай бог мне его неудобно читать — сам виноват.
Код на go на 20-30 процентов короче аналогичного на яве (там просто не лишних слов, например, нет точки с запятой в конце каждого предложения, нет круглых скобок в операторах условия или цикла etc)
У меня такое ощущение, что где-то в мире сидят программисты, чье единственно ограничение — скорость набора, и вместо книг по программированию они ходят на курсы по скоростной печати. Остальные разницы в 20% не почувствуют, и это с Java — невероятно многословным языком.
Короче, то ли реализация принципов сомнительная, то ли примеры.
P.S. Пожалуйста, давайте не будем начинать холивар. Меня интересует Go, и это неплохой язык (как и большинство остальных). К сожалению статьи о нем на Хабре зачастую неоднозначные и вызывают кучу срачей.
Grief
30.07.2016 08:12+1Вы все грамотно написали, не холивара ради я лишь хочу варизить одну свою мысль. При сравнении языков программирования все величины относительны. Ничего не удастся привести к единой шкале просто потому что языки различны. Производительность? В какой момент времени, сразу после старта или после прогрева виртуальной машины? В каких условиях, под какой нагрузкой — слишком много условных переменных. Читаемость, понятность, поддерживаемость? Ну это вообще настолько субъективно, насколько возможно. Если бы это было не так, то не существовало столь большого числа языков на сегодняшний день. Кому-то нравится питон, кому-то больше по нраву руби. Кто-то вообще не считает интерпретируемые или выполняющиеся в ВМ языки настоящим языками. Да, возможно, история склонила определенные языки к определенным целям, условно, си — железо, перл — обработка текста, питон — математическое прототипирование и т.д. Но все же, популярность языка обуславливается свойствами, перпендикулярными всем вышеперечисленным. Мне кажется, что для того, чтобы прижиться, язык должен следовать тем же правилам, что и любой другой программный продукт. А для любого программного продукта в первую очередь важен маркетинг. Даже если продукт бесплатный. В первую очередь, важно, кто стоит за языком. Майкрософт, Гугл, Эппл или Гвидо. Здесь играет роль и психология, наверное. Но вообще, я хотел о другом сказать. Есть единственное исключение, позволяющее сравнить языки по-честному. И это — краткость языка. Речь, конечно, не идет об обфускации. Когда я изучил питон после джавы, я был удивлен, насколько короче можно записать то же самое. Почему это важно? Дело, разумеется, не в том, что программист упирается в скорость набора, а в том, что чем меньше связующего кода и лишних абстракций, тем яснее можно увидеть сам алгоритм, тем меньше приходиться тратить внимание на вещи, прямо не связанные с задачей. Да банально уставившись в экран кода, видишь больше, иногда в разы. Взять, например, геттеры-сеттеры явы, больная мозоль для многих и камень преткновения. Факт в том, что даже будучи автогенеренными, они создают огромное количество шума, который нужно учитывать. Или все эти public static final void… зачем они нужны? Короче говоря, для себя я решил, что краткость кода — одна из первостепенных по важности вещей.
Sirikid
30.07.2016 14:19+6Go явно не лучший язык с точки зрения краткости. Может Java и многословней, но её система типов мощнее и есть огромная куча языков которые можно использовать вместо неё — Scala, Kotlin, Clojure, а для ценителей даже Haskell (Frege).
Idot
30.07.2016 14:26+1единственное исключение, позволяющее сравнить языки по-честному. И это — краткость языка
Вот потому-то и я мечтаю изучить APL — очень красивый и ёмкий язык!softaria
30.07.2016 19:11+3Я бы сказал, что важна не краткость, а низкий уровень шума и простота восприятия.
Мне нравится критерий, который сформулировал Grief — язык тем лучше, чем больше смысла я вижу на одном экране.
При том, что код писал не я и я — не гений, а среднестатистический специалист.webkumo
31.07.2016 19:17+1Так перл же тогда! На одном экране можно увидеть всю не самую простую программу! Весь её смысл! Вот только как вы её понимать-то будете после этого?
softaria
31.07.2016 19:22+1Именно для этого я уточнил, что условеный «я» — не гений. Не пойму я её.
Как не пойму, например и вот такой код на scala
object IsHCons1 { type Aux[L[_], FH[_[_]], FT[_[_]], H0[_], T0[_] <: HList] = IsHCons1[L, FH, FT] { type H[t] = H0[t] ; type T[t] = T0[t] } def apply[L[_], FH[_[_]], FT[_[_]]](implicit tc: IsHCons1[L, FH, FT]): Aux[L, FH, FT, tc.H, tc.T] = tc implicit def mkIsHCons1[L[_], FH[_[_]], FT[_[_]]]: IsHCons1[L, FH, FT] = macro IsHCons1Macros.mkIsHCons1Impl[L, FH, FT] }
И имено поэтому ни Perl ни Scala по данному критерию будут оценены не очень высоко.Randl
31.07.2016 19:51Чтобы читать код, не надо быть гением. Надо знать язык.
softaria
31.07.2016 20:03+1Чтобы читать такой код с большой скоростью и в промышленных объёмах, надо быть именно гением.
Большинство людей тоже сможет его прочитать, но мы затратим на это слишком много усилий.
Язык — прежде всего инструмент. В идеале, человек должен иметь дело исключительно со сложностью своей задачи, а не с дополнительной сложностью, привносимой языком.vadim_shb
31.07.2016 23:17+2У scala есть такая проблема. Многие библиотеки, в том числе стандартная, написаны очень непросто. Это или легаси, или описания DSL, удобных для применения сторонними разработчиками. Команда EPFL над этим работает, и потихоньку улучшает ситуацию. Многие вещи переписывают с нуля. Вводят дополнительные правила компиляции не позволяющие творить жесть в коде. Радует то, что во время разработки заглядывать в подобный код приходится крайне редко. А свой код можно держать в абсолютно читаемом виде. То есть работе это не мешает.
solver
31.07.2016 23:28+2«Можно» не означает «Нужно обязательно»
Все пользуются ножами на кухне для резки продуктов.
А ими ведь можно порезать себе пальцы… но как часто реально люди это делают?
Одна из прелестных и сильных сторон Scala, как раз в разделении прикладной разработки и библиотечной.
Для прикладной разработки все эти навороты не нужны.
Эти навороты пишут ребята «семи пядей во лбу» и они их читают в лет.
Они делают библиотеки для не таких опытных разработчиков.
И это очень хорошо, что профи используют хорошие навороченные перфораторы, а не зубило с молотком.
В Go же все вынуждены пользоваться зубилом и молотком. Да, это проще, да, это понятнее.
Но все это напоминает старый анекдот «Пилу точить некогда, пилить надо».
senia
01.08.2016 01:01+4В этом коде, кстати, читать вообще нечего.
Это же из shapeless наверняка. И читается, при знании shapeless, без проблем.
В scala (особенно в shapeless) встречается сложный для понимания код, но это не тот случай.
kuftachev
31.07.2016 18:43По компактности, с Perl вообще мало что рядом сможет стоять, но как-то на нем пишут в основном администраторы.
Falstaff
30.07.2016 08:12+2Справедливости ради, с недавних пор динамическая загрузка в Go так-таки появилась. Плюс статической компоновки по умолчанию — это то, что получаются самодостаточные бинарники, которые зависят разве что от libc. На практике получается очень приятно, что можно отгрузить куда-то один файл и быть достаточно уверенным, что он не упадёт из-за неудовлетворённой зависимости.
С автоформатом — да, если кто-то предпочитает другой формат, с Go получится неудобно. С другой стороны, приятие формата суть дело привычки. Вообще, в Go много крутилок и кнопочек принесли в жертву богу быстрой командной разработки — там всё сделано ради того, чтобы только что пришедший в команду джуниор или интерн начал быть эффективным на третий день вместо того чтобы неделю лупать глазами на непривычный формат кода, ещё неделю чертыхаться на отвергаемые (отформатируй согласно гайдлайнам проекта и приходи снова!) коммиты и подобные вещи. Я не берусь спорить, правильно это или нет, но определённая логика в этом есть.RomanPyr
30.07.2016 11:48К слову сказать, писать Go код можно любым удобным для себя форматированием. Главное Git-хук на go fmt поставить.
И тогда гошное форматирование будет на уровне автозамены CRLF.
Читать да, только в каноничной форме :)
Randl
30.07.2016 16:01На практике получается очень приятно, что можно отгрузить куда-то один файл и быть достаточно уверенным, что он не упадёт из-за неудовлетворённой зависимости.
Статическая компоновка есть и в других языках. Смысла запрещать динамическую я не вижу.
чтобы только что пришедший в команду джуниор или интерн начал быть эффективным на третий день вместо того чтобы неделю лупать глазами на непривычный формат кода, ещё неделю чертыхаться на отвергаемые (отформатируй согласно гайдлайнам проекта и приходи снова!) коммиты и подобные вещи.
Я не знаю как у вас, но в моей IDE есть автоформатирование кода. Весь читаемый мной код я прогоняю через него, получая привычный мной формат. Это решает те же проблемы, но никак никого не ограничивает.
Falstaff
30.07.2016 16:25Статическая компоновка есть и в других языках. Смысла запрещать динамическую я не вижу.
А кто-то запретил? В Go есть динамическая компоновка (я вроде бы упомянул ответом выше), статическая там просто по умолчанию.
По поводу форматирования — ну хорошо, чужой код вы прогоните через автоформатирование и будете читать так, как вам нравится. Но писать-то вам код придётся в соответствии с гайдлайнами того проекта, куда вас позовут. Или вы конвертируете и туда и обратно? Переформатируете всё написанное перед коммитом? Кстати, если что, с Go вам тоже никто не мешает так сделать. Просто есть официальный стандарт оформления и есть официальная утилита, которая форматирует. На вашей машине никто вас не заставляет ими пользоваться, дело хозяйское.Randl
30.07.2016 16:38+2А кто-то запретил? В Go есть динамическая компоновка (я вроде бы упомянул ответом выше), статическая там просто по умолчанию.
Я так понял, что изначально ее не было.
Просто есть официальный стандарт оформления и есть официальная утилита, которая форматирует. На вашей машине никто вас не заставляет ими пользоваться, дело хозяйское.
То есть это не требования, а рекомендации? Но тогда все равно каждый будет форматировать как ему угодно. Возникает ощущение, что Go — язык непонятных искусственных ограничений.
Falstaff
30.07.2016 17:16Изначально не было. Ну так и язык относительно новый, во многих языках изначально много чего не было. Её не запрещали, её просто не сделали сразу. Вопрос приоритетов. Питону необходимость везде тащить рантайм и отсутствие динамических библиотек (хотя вроде уже можно что-то такое с Cython сделать? пусть знающие поправят) не мешает в топе TIOBE висеть и пользоваться народной любовью.
Да, это не требования — не ограничения — а рекомендации. Поэтому я не совсем, признаться, понимаю, откуда ощущение взялось. Тут фокус в другом — есть такая штука как сила умолчаний. Если в языке из коробки есть официально рекомендованный стиль оформления и даже утилита, то в сообществе создаётся тренд, и очень немногие от него отходят. Получается, что и волки сыты (можно форматировать как угодно, если есть желание), и овцы целы (подавляющее большинство кода всё равно в стандартном единообразном стиле). Это просто психологический приём, чтобы большинство разработчиков безболезненно и быстро миновали фазу «так, в каком стиле мне начать писать код» и начали писать собственно код.grossws
30.07.2016 17:44+2Да, это не требования — не ограничения — а рекомендации.
Тогда странно выглядит то, что сначала очень старательно продавали статическую линковку как killer feature. Удивительное будет время, когда найдут какой-нибудь приятный баг где-нибудь в crypto. Сколько народу не пересоберёт (учитывая, что используют glide/gob далеко не везде), а сколько — забьёт?
Falstaff
30.07.2016 18:05И сейчас продают, и, по-моему, правильно продают. Killer feature в общем-то не сама статическая линковка как таковая, а то что она получается сама, по умолчанию, без каких-либо ментальных или физических телодвижений. Это всё та же сила умолчаний — у статической линковки есть плюсы, но чтобы использовать её в других языках, надо поработать, а тут получается бесплатно.
По поводу багфиксов — это старый спор, и я не думаю, что там есть какая-то правда. Это больше спор о том, кому быть виноватым — майнтайнерам пакетов с библиотеками, майнтайнерам приложений, или вообще нерадивым админам, которые ничего и никогда не обновляют. Если так подумать, то с тем же успехом можно накатить обновление библиотеки с незамеченным zero day (а может и с нарочно внесённым), и моментально все динамически слинкованные приложения становятся уязвимыми. Мне кажется, там проблема вообще в другой плоскости лежит.
grossws
30.07.2016 18:15Тут рядом ещё ходит проблема невоспроизводимых билдов благодаря утилите
go get
, которая местами усиливает (более новая версия в репозитории может оказаться несовместимой и софт оставят необновлённым), местами — ослабляет (go get
принесёт последнюю версию зависимости) вышеописанную проблему. Ну и всё это надо помножить на реальное разнообразие: кто-то вендорит зависимости, кто-то говорит "дёрните go get ..." при сборке; кто-то предупреждает о необходимости чистогоGOPATH
, кто-то предполагает, что он у вас единственный и вы будете использовать те же версии библиотек, что и в других своих проектах.
Меня лично радует, что glide пошёл в массы, но это очень субъективная штука, т. к. я на go не пишу, то, по сути, рассматриваю проблемы с точки зрения мейнтейнера, а не разработчика.
Falstaff
30.07.2016 18:53Да, это больной момент у всей экосистемы. :( Зря на потом оставили. Я думаю, что вендоринг если не решит проблему, то хотя бы однородной сделает. Кстати, спасибо за наводку на glide, я пользовался gb-vendor, но glide выглядит хорошо (я тоже ничего на Go по большому счёту не пишу, но быть в курсе стараюсь).
Randl
30.07.2016 19:58без каких-либо ментальных или физических телодвижений
Я пишу на С++, телодвижения сводятся к указанию пути к библиотеке и подключению заголовка. Куда уж проще?
Falstaff
30.07.2016 20:26+3Я тоже пишу на C++. Добавьте телодвижения автора библиотеки, который обеспечил возможность сборки статической библиотеки, и майнтайнеров пакетов, которые собрали её под нужную архитектуру и дистрибутив и доставили вам. :) Представьте, что в репах статической библиотеки нет (или вообще нет). И автор не предусмотрел сборку статической библиотеки (или вообще чего-нибудь толкового, или всё зависит от экзотичной системы сборки с запутанными и хрупкими конфигами). Мне в целом нравится, на чём я пишу, но мне кажется, что «куда уж проще» — это не про сборку и зависимости в C++. :)
OnYourLips
30.07.2016 22:27+1У вас были программы покрупнее, чем те, которые требуют всего одну библиотеку?
В моем текущем проекте их больше сотни, а ведь надо их не просто прописать, а ещё и скачать. И не просто скачать, а скачать нужные версии таких зависимостей. Причём так, чтобы друг с другом они не конфликтовали.
И прочитать инструкции по сборке, которые у многих библитотек построены на разных инструментах.
А если надо обновить библиотеку, то снова придётся переделывать часть этой работы.
Сколько суток займёт такая задача для C++, я даже не представляю, но явно не менее недели. А в моем проекте на другом языке это дело минуты.Randl
30.07.2016 22:48Были, но они подключались по одной в процессе разработки. Больше получаса на поиск библиотеки с нужным функционалом, её сборку и подключение уходило редко.
Хотя если их несколько сотен, то и правда уйдет неделя.
sleeply4cat
30.07.2016 22:39А что сейчас пишут на плюсах?
Прочитал «21 день», пока в отпуске был. Теперь меня терзают мысли про то, что с этим языком что-то серьёзно не так. Начиная с невозможности получить размер массива по указателю, хотя по логике он должен храниться в аллокаторе памяти, и до странной магии ручной расстановки меток виртуальных функций, которое, как мне кажется, компилятор вполне может делать сам. Всё это выглядит как хождение по заряженным арбалетам: никогда не знаешь, какой выстрелит. Это я что-то делаю не так, или язык действительно безнадёжно затянут в бездну обратной совместимости?Randl
30.07.2016 23:00+2
Если серьезно, то на плюсах пишут там, где нужна максимальная производительность. Несмотря на все его недостатки (а каждый находит десяток-другой своих), реальной альтернативы нет. Возможно, ей станет Rust.
З.Ы. В С++ есть std::array и std::vector, зачем пользоваться сишным массивом?
sleeply4cat
30.07.2016 23:09Да просто 21 день — единственная книжка на русском языке с элементами С++11, которую нашёл перед уездом.
Про array знаю, просто привёл пример того, что на самом начальном уровне меня покоробило.
DarkEld3r
01.08.2016 12:53или язык действительно безнадёжно затянут в бездну обратной совместимости?
Не без этого. Вот только те проблемы, что вы перечислили они не про обратную совместимость, а про нежелание жертвовать производительностью. Скажем, как компилятор сам расставит "метки виртуальных функций", если вы пишете библиотеку?
В более новых языках типа Rust действительно многое проще (в том плане, что компилятор даст по рукам, если что), но суть остаётся той же: такие решения приходится принимать самому: если нужные виртуальные функции, то используем трейт-объекты и т.д.
0xd34df00d
03.08.2016 01:33Пишу высокопроизводительный код с матаном. Упираюсь при молотиловке чисел в производительность памяти. Хорошо.
Размер массива по указателю, впрочем, получать особо не нужно было. Да и как компилятор метки виртуальных функций расставить может, если полной информации о всём дереве наследования в общем случае у него может и не быть?
shytikov
30.07.2016 17:23+2Там всё плохо… Есть динамическая линковка — опция компилятора
-dynlink
. Это, насколько я понимаю, вызов кода из стороннихso
иdll
. Но свою динамическую библиотеку создать на Go — нельзя. И также нельзя подгрузить в рантайме произвольную библиотеку и вызвать из неё функцию.
Другими словами, реализовать плагины в программе просто невозможно. И это главная проблема сейчас, как по мне. Это тормозит развитие http://gogs.io/, чтобы решить эту проблему ребята из http://caddyserver.com/ написали своё решение, которые перекомпилирует исходники с нужными модулями по выбору пользователя...
Вот, к примеру, один из тасков о динамической загрузке. Закрыт. Заброшен: https://github.com/golang/go/issues/13751
Falstaff
30.07.2016 17:29А
-buildmode=c-shared
, которая в 1.5 появилась, это не оно? Можно из Go сделать.so
, потом использовать откуда угодно, в том числе из Go. Понятно, что не без ограничений по экспортам, но всё же. Вот тут подробнее: http://www.darkcoding.net/software/building-shared-libraries-in-go-part-1/shytikov
30.07.2016 17:58+1Но можно ли эти
so
илиdll
загрузить обратно в Go динамически? Вызвать функцию, а потом выгрузить из памяти?
Как я могу реализовать систему плагинов к моему приложению на Go без перекомпиляции оного?
Falstaff
30.07.2016 18:35Именно чтобы руками, как с
dlopen()
илиLoadLibrary()
? С этим пока не очень просто. В принципе, насколько я понимаю (поправьте, кто это дело ковырял), можно загрузить черезcgo
. Код получается, мягко говоря, некрасивый, и не уверен, как сделать на не-POSIX платформе, но в целом должно работать. Что-то вроде такого:
// #cgo LDFLAGS: -ldl // #include <dlfcn.h> import "C" // ...и дальше по тексту, handle := C.dlopen(...) и прочее.
Насколько удобно будет так делать развесистую систему плагинов — не знаю, надо пробовать и смотреть. Ну и, понятно, портируемость пострадала.
QtRoS
30.07.2016 08:50+11А я вообще не соглашусь с тем, что код на Go короче. Я пробовал, получилось более многословно, максимально приближено к C в плане последовательности действий, разве что очисткой памяти занимается сам рантайм.
zim32
30.07.2016 00:39+2>>Но очень быстро все уперлось в производительность.
>>На одном сервере можно было запустить не более 300 клиентов.
Я конечно извиняюсь, но думаю после этого можно не читать дальше. А в го у вас сколько клиентов получилось? 310?DragonFire
30.07.2016 00:40+8Статью не читаю, комментарии пишу. Автор же написал что 2500
zim32
30.07.2016 00:43+9Ну т.е. после того как он стал использовать профилировщик (который никто ему не мешал использовать на джаве) он оптимизировал приложение. Это явно плюс языка go
Я думаю что го был создан для дешевой раб силы, все его ограничения связаны с низким порогом вхождения дабы не заморачивать светлые умыDragonFire
30.07.2016 00:46+1Автор подробно описал причины почему он использовал профилировщик на го и не использовал на джаве. А еще комментарием выше ему явно указали как он мог бы таки его использовать.
И то что автор не использовал профилировщик не объясняет почему вы не читаете статью, но оставляете комментарии…zim32
30.07.2016 00:52+6Потому что заявления — я написал сервер на джаве и он обрабатывал всего 300 клиентов (без тех. подробностей) это какая-то софистика.
А я вообще использовал nodejs который обрабатывал пол миллиона клиентов, так что давайте все использовать nodejs )Moxa
30.07.2016 02:05+1мне как-то скучно было и я на жавоском сервере на домашнем компе поднял 2 миллиона активных соединений, потребовалось 10гб оперативы, но старенький амд осилил ^_^
zim32
30.07.2016 02:13+3Ну а на го вы подняли бы примерно 16млн ;) судя из статьи
softaria
30.07.2016 09:11-5Если там просто пустые соединения, то разницы бы не было.
Если сервер имеет сложную логику и «тянет» мало клиентов, то вывести его на нужный уровень производительности в go займет существенно меньше времени, чем выполнение той же задачи в java.
(Хотя, разумется, это возможно и в java и вообще на любом языке)
softaria
30.07.2016 08:18Сервера бывают разные. Ваши полмиллина клиентов — это игровые клиетны в реальном времени, как у меня?
Кроме этого, вы не захотели понять суть статьи. Она не о том, что go — лучший язык.
И не о том, что в ява нет профайлеров.
Я сравнил усилия, которые от меня потребовали языки, чтобы сделать одно и то же. Go в данном случае потребовал в разы меньше.
RaaaGEE
31.07.2016 18:42+3Я сравнил усилия, которые от меня потребовали языки, чтобы сделать одно и то же. Go в данном случае потребовал в разы меньше.
Да ладно? Вы даже не пытались профайлить в джаве, о каких таких «потребовал в разы меньше» можно говорить?SirEdvin
31.07.2016 18:44Как я понял, у автора «потребовал в разы меньше усилий» процесс профилирования, собственно.
softaria
31.07.2016 18:55Не только он. Существенная экономия была достигнута за счёт профилирования и за счёт ловли race conditions.
Несущественная — за счет меньшего объема кода.SirEdvin
31.07.2016 18:56+4Комментарий на который я ответил, как бы подразумевает, что вы не можете сравнивать сколько вы времени сэкономили, потому что профилировать код на Java вы даже не пытались.
Поэтому в статье у вас и получилась экономия только на том, что вы быстрее освоили один профайлер, чем другой.softaria
31.07.2016 18:57Ответил ниже. Могу. Потому что неоднократно ранее делал это с другими проектами.
SirEdvin
31.07.2016 19:05+7Хм, вот тут я вас не очень понимаю.
Если вы уже делали профилирование на других проектах, то у вас уже должны быть достаточные навыки для работы с профилированием в Java, что бы не писать о том, какое оно сложное и не понятное.
То вы указываете, что работаете с Java целых 18 лет, но почему-то у вас свеженаписанный сервер не держал больше 300 коннектов, что явно указывает на то, что для его написания не использовались нужные технологии.
Так же, непонятки с профилированием, хотя за 18 лет, у вас точно должен был быть опыт профилирования хотя бы одного многопоточного приложения на java, а тулзов для race detector там полно.
Так же. вы тут где-то признавались с том, что не работали/не знаете ни одну библиотеку, для работы с серверами на Java, что еще более странно, с 18-летним опытом, если даже я, который впринципе не работает с Java в production, поработал с Netty.
Как-то немного многовато нестыковок.softaria
31.07.2016 19:14Достаточные навыки в чем-то не противоречат отношению к этом чему-то, как к сложному и неудобному.
Про сервер вы правы. Ранее я писал на java что угодно (начиная от web (бизнес системы) и кончая играми, Eclipse RCP или CORBA-SNMP gateway), кроме серверов реального времени, использующих Websocket. Этот сервер (а точнее — прототип) я написал очень быстро и без оглядки на performance. На этом этапе я определял что вообще должен делать этот сервер, по сути — проектировал игру. С технологией (библиотекой) я, кстати, действительно, ошибся.
Performance-ом собирался заняться на следующем этапе. Уже «предвкушал» приятную возню с VisualVM. Но наткнулся на описание профайлера в языке go (на который уже давненько с интересом посматривал). Описание понравилось. Решил сделать production вариант на go. Сделал. Опытом более чем удовлетворен.
softaria
31.07.2016 18:56-1Вы путаете две вещи «я не пытался профайлить именно этот проект» (да, не пытался. Примерно знал во что оно выльется) и «я не пытался профайлить в java вообще» (такой опыт был, иначе не о чем было бы говорить)
Ramzeska
30.07.2016 01:03+2Го задалбывает приведением типов. И функции которые конвертнут из одного типа в другой всегда болтаются в разных библиотеках. Я был бы счастлив если был бы какой-то единый способ приведения стандартных типов. Есть странные вещи, например в условиях нельзя сравнивать целые и дробные, это очень бесит в циклах.
nehaev
30.07.2016 01:06+21Вот это проблемы у людей!
Нет бесплатного профайлера в Java? Конечно есть, хорош для решения основных пробем с производительностью, имеется куча плагинов, называется VisualVM.
Нельзя подключиться профайлером к удаленному серверу? Конечно можно, включаем JMX, пробрасываем порт и вперед. На самом сервере всегда можно заюзать консольные утилитки типа jmap, hprof и т.п.
Race conditions — это действительно головная боль писателей многопоточных приложений, но далеко не всех. Некоторые все-таки знают про shared mutable state и избегают его, используя либо стратегию share-nothing (каналы в Go, Akka — в Java), либо функциональное программирование (переход на immutable).
Стоит ли ява программисту полностью переходить на go? Нет.
А вот с выводом-то особо и не поспоришь :)softaria
30.07.2016 08:48-12Ваша мысль выглядит примерно так «Нельзя удалять гланды автогеном? Конечно, можно! Просто надо делать это через задний проход!»
Я нигде не сказал, что в яве нет профайлера.
Я сравнивал производительность инструментов (java + какой-то профайлер) vs (go + встроенный профайлер)
Go в несколько раз выиграл в моём случае. Работать было быстро, удобно и приятно.
AterCattus
30.07.2016 01:15+7Глаз сильно зацепился за это
Но важно понимать, что этот самый коллектор будет запускаться каждые несколько секунд и заметно притормаживать систему.
Это ж насколько сильно нужно гадить в хип, чтобы заметить работу GC? Это точно не про Java?Laney1
30.07.2016 08:19в go до недавнего времени применялся сборщик «stop the world», без ручного тюнинга паузы могли доходить до нескольких секунд. Но потом GC полностью переписали (сделали конкурентным), и сейчас все должно быть хорошо. Если интересно, то погуглите, на хабре есть несколько статей на эту тему.
AterCattus
30.07.2016 14:30+2Ну так мы и не про Go1.2 какой-нибудь сейчас говорим, верно? На 1.4 еще помню какие-то задержки на сотни мс, сейчас же на 1.6 даже 10-12 мс — это уже зачем-то много гадили в хип. Типичное время работы GC <= 1мс на наших проектах.
softaria
30.07.2016 08:22-6Нужно завести игровой сервер. Поднять там 2500 клиентов, каждый из которых будет отправлять в среднем 50 сообщений в секунду и получать примерно 750 (через web socket).
Работа gc замечается в едва заметных глазу лагах при передвижении игровых объектов.Suvitruf
30.07.2016 10:58+10Так это не gc скорей всего виноват, а вы с объектами, вероятно, неправильно работаете. Часто инстанциируете, нету пулов и т.п. У нас сервера игровые на java/C#, никаких лагов не наблюдаем связанных с gc.
softaria
30.07.2016 11:27Что касается объектов, то нет. Мы как раз оптимизировали здесь всё, что только можно было. В куче почти ничего не создаётся. Пулы есть.
Возможные причины такой разницы:
1) GC в go пока хуже, чем в java. До версии 1.5 был вообще ужасен. Но всё еще заметно хуже.
2) Разная нагрузка на сервер. Наш получает от каждого из 2500 клиентов примерно 50 сообщений в секунду. Обратно отсылает примерно 750. Плюс имеет очень много межпоточных коммуникаций.
3) Разные требования к серверу, обусловленные устройством самой игры. Если у нас влючить gc, появлется едва заметное дрожание кораблика раз в несколько секунд. Оно трудноуловимо, но создает ощущение, что с игрой что-то не так.AterCattus
30.07.2016 14:44+1GC может и похуже, но:
- escape analysis позволяет много чего оставить на стеке и уменьшить мусор в хипе;
- многие типы нативны и хранятся как есть без лишних косвенных обращений, уменьшая нагрузку на GC при сборке
И получается хорошо на больших хипах (десятки ГБ).
P.S. У нас на пушилках, рассылающих около миллиарда пушей в сутки каждая (с огромной кучей логики, горутин, каналов, и т.п.), сейчас сборка gc занимает 12мс время от времени (и там даже sync.Pool почти нет).
На более оптимизированных (пулы и профилировка наше все) демонах сборка редко когда даже 1мс занимает.
ZOXEXIVO
30.07.2016 02:02+19Смешно наблюдать за этими потугами недоразработчиков.
Я из .NET, но тут я с Java.
Сколько же вас развелось таких, кто не написав ничего серьезного и не имея за плечами нормального опыта, прыгают с языка на язык и успевают между этим писать поучительные статьи? Другие успевают преподавать с таким «богатым» опытом.
Да, чувак, то что ты не умеешь пользоваться инструментами — это Java виновата, совершенно точно. проблема точно в ней!softaria
30.07.2016 08:57-7Поясните каким образом вы оценивали мой опыт и почему решили, что я прыгаю с языка на язык?
Что касается инструментов, то лучшие инструменты остаются лучшими, несмотря на то, что я или вы умеете работать и с плохими.
divan0
31.07.2016 15:48-4Чем больше общаешься в англоязычных коммьюнити, тем страшнее читать вот такие комментарии, которые ещё и кто-то плюсует.
Автору статьи огромнейший респект, за потраченное время, за умение выйти за рамки одной технологии, за желание поделиться опытом с другими и за отличную подачу. Это нужно поощрять и развивать.
А вот почему вы считаете, что вы имеете права оскорблять других людей за их труды, мне не ясно. К сожалению, о русскоязычных коммьюнити мнение складывается по вот таким вот зазнавшимся «специалистам, написавшим много серьезного», как вы.SirEdvin
31.07.2016 18:43+6Я все еще не понимаю, почему вам не нравятся такие комментарии.
Они абсолютно справделивы.
Go-коммюнити в Рунете уже достало писать такие статьи, где они сравнивают какой-то язык с Go, допуская в сравнении серьезные ошибки.
По сути, всю статью можно было назвать: нагуглить инфу про профайлеру в Go проще, чем по профайлеру в Java.divan0
01.08.2016 09:28+1Если вы не понимаете, почему оскорблять людей это не есть хорошо — я вам не объясню.
Касательно статьи — пусть даже автор 1000 раз не прав, ему можно указать на ошибки уважительно и без оскорблений. Это будет правильней по всему пунктам. Почему-то в рунете это не сильно практикуется, увы.
Опыт работы с профайлером в Go, кстати, и вправду, великолепен. Это не про «нагуглить» это про реальную продуктивность и затраченное время и когнитивные усилия от возникновения проблемы до ее фактического решения с помощью профайлера.SirEdvin
02.08.2016 08:12Поговорив с автором я вытянул из него, что у него довольно богатый опыт с VisualVM и он от него устал. Это существенно дополнило мое впечатление о статье.
Касательно статьи — пусть даже автор 1000 раз не прав, ему можно указать на ошибки уважительно и без оскорблений. Это будет правильней по всему пунктам. Почему-то в рунете это не сильно практикуется, увы.
Можно сказать спасибо "интересным" статьям про Go ранее. Например, ту, в которой у компании крутились микросервисы на Java в Tomcat.
ZOXEXIVO
31.07.2016 21:42+3Если я в тексте вижу фразы — «я тут написал, а оно не работает, наверное такое на Java вообще не возможно написать», и еще приплести сюда какой-то недоразвитый язык и поставить его выше прекрасно зарекомендовавшего себя инструмента, который используют десятки лет, то готов многое высказать такому специалисту.
И ведь, какой-нибудь школьник почитав этот «труд» реально подумает, что лучше Go ничего нет, а это уже просто диверсия какая-то.
Иногда складывается впечатление, что это какие-то новые маркетинговые войны и реклама идет самыми грязными методами и просто внаглуюsentyaev
01.08.2016 02:30+3Помню, будучи «школьником», прочитал в книге или статье, уже и не вспомнить одну интересную мысль — «если у вас что-то не получается, или что-то не работает, не ищите проблему во фрэймвоке или библиотеках, ищите проблему в вашем коде».
Почему-то мне это прям на подкорку засело.
Так вот, за свои 10 лет работы, мне всего лишь один раз вствил палки в колеса IIS7, и то, просто потому, что я не знал одну его особенность по сравнению с IIS6. Мы с товарищем просидели пару дней дебажа ASP.NET.
А ведь могли просто сказать — «это слишком сложно, или невозможно».
divan0
01.08.2016 09:39+2Это справедливо, если вы ограничены одной технологией в принципе. Но чем больше вы набираетесь опыта, тем больше понимаете, что выбор технологии (языка/базы данных/алгоритма/фреймворка/etc) это тоже часть работы инженера, и едва ли не важнейшая.
Ограничивая свои знания одной технологией, вы повышаете свой knowledge debt, который будете выплачивать тем, что будете менее продуктивны. Вы могли бы точно так же зафанатеть по фортрану и считать, что те, кто предлагают вам другие языки «просто недостаточно хорошо разобрались» в фортране. Нет, нет и нет. Это ваша ответственность максимально объективно владеть ситуацией, знать плюсы и минусы технологий, уметь использовать как-минимум основные из них и уметь выбирать нужный инструмент для нужной задачи.
Религиозный фанатизм тут к добру не приводит и понижает ваш уровень как специалиста очень существенно.iqiaqqivik
01.08.2016 09:44+2Безусловно, просто го — это гигантский прыжок назад по сравнению с джавой в сегодняшнем мире. Овладевать языком имеет смысл тогда, когда он _лучше_, а не когда он _проще_.
Ну, если, конечно, нет цели устроиться чернорабочим в гугл.divan0
01.08.2016 12:53Безусловно это только в вашем джава-мире, из которого автор, в отличие от многих комментаторов сумел выглянуть. А субъективные рассуждения про «сложнее значит лучше», с которыми я в корне не согласен, и «чернорабочие в гугл» — это вообще никакой критики не выдерживает.
iqiaqqivik
01.08.2016 13:22+3> субъективные рассуждения про «сложнее значит лучше», с которыми я в корне не согласен
А-а-а-а, у вас с простыми силлогизмами, оказывается, проблемы. Я нигде не утверждал, что «сложнее — значит лучше». Я уж молчу про то, что никогда в жизни не принадлежал джава-миру, и писать код на джаве не стану, даже если от этого будет зависеть моя жизнь.
Просто я умею просматривать за ужином бенчмарки, а не доверять без разбору непонятно откуда взявшимся текстам.
sentyaev
01.08.2016 13:30+1Я не говорил, что есть технологии лучше или хуже.
Но чем больше вы набираетесь опыта, тем больше понимаете, что выбор технологии (языка/базы данных/алгоритма/фреймворка/etc) это тоже часть работы инженера, и едва ли не важнейшая.
Знать алгоритмы нужно, понимать разничу между разными типами БД тоже.
Языки и фрэймворки… да какая разница? Вы действительно думаете, что есть хоть какая-то разница между RoR, JavaEE, ASP.NET и Spring? Ну да, некоторые фичи где-то из коробки, а где-то отдельной либой подключить, но по сути это одно и тоже.
Причем все новые технологии которые мне интересны я пробую. Могу код почитать, если решение мне кажется интересным.
Все остальное это дело вкуса разработчиков.
Randl
01.08.2016 11:02+2В это веришь до первого пойманного бага в компиляторе :)
sentyaev
01.08.2016 13:22+1Так в этом и смысл, чем больше вы работаете с чем-то, тем больше вы узнаете.
Ведь любая в любой технологии есть баги и ограничения, с опытом все это узнаешь и это позволяет не вставать на одни и те же грабли.
А если постоянно менять эти технологии, то и на грабли будешь вставать каждый раз.Randl
01.08.2016 14:54Я вот об этом:
если у вас что-то не получается, или что-то не работает, не ищите проблему во фрэймвоке или библиотеках, ищите проблему в вашем коде
После того как репортишь или просто обнаруживаешь баг в компиляторе, перестаешь мыслить так категорично.
sentyaev
01.08.2016 15:06А, так это совет именно для начинающих, а не тех кто дошел до того, что репортит баги компилатора.
Суть в том, что новички часто пытаются найти какой-то такой идеальный вариант где все хорошо, нет багов и почти не нужно писать код. И часто прыгают от одной технологии к другой. Типа пару лет пописали на .net, потом вышел nodejs и он почему-то лучше всех, теперь появился Go и нужно срочно переходить на него.
Причем все пытаются привести такой аргумента как продуктивность. А по сути, те же яйца, и через пару-тройку лет и пару-тройку сложных проектов точно так-же находятся баги в тулах и компиляторах.
divan0
01.08.2016 09:33-2приплести сюда какой-то недоразвитый язык
Вы же понимаете, что с такой риторикой с вами общаться, как со взрослым человеком, нет смысла, правда?
Если бы мне пришлось выбирать из двух кандидатов в свою команду, я бы однозначно выбрал автора статьи, а вас бы сразу в черный список занёс. Автор умеет осваивать новые вещи, умеет учиться, умеет делиться знаниями и не боится почувствовать себя новичком. Это очень ценно. Вы же фанатичны в одной технологии, не умеете адекватно общаться, обвешались в стереотипах и не умеете объективно смотреть на выбор технологии, как на один из важных элементов работы разработчика. По-моему, выбор очевиден.ZOXEXIVO
01.08.2016 10:19+6Вы вроде взрослый человек, а ведетесь на какие-то, очень странные вещи.
Вы видимо, тоже проскочили уровень, где начинаешь смотреть на ващи более трезво.
С чего вы взяли, что человек выше будет учится и делать что--то лучше? Он язык приплетает для технологии, в некоторых случаях, это бывает оправданно. Такие люди будут вас доить, каждый год переписывая свое творчество на очередной язык.
Go хорош для сетевой мелочи и не больше.
Уж называть меня консерватором в технологиях просто смешно.
Просто вы своими (Go) статьями, честно, уже достали.divan0
01.08.2016 12:58-7Просто вы своими (Go) статьями, честно, уже достали.
Вы всегда можете пойти в угол и поплакать, если кто-то пишет статьи про ненавистную вам технологии. Очень взрослый уровень хабра и русскоязычного джава-сообщества в целом.webkumo
01.08.2016 15:49+3А вы смеееешноой…
Т.е. увязывание тезисов являющихся явно холиворными в статье — вы называете взрослым поведением? Вы или пропустили их (соглашаясь с авторским фанатским мнением по этим пунктам) или явно троллите. Да и в комментариях автор так и не смог внятно назвать/показать плюсы перехода. И после этого вы его называете новатором? Простите — но в шею гнать таких новаторов!
Для большей ясности процитирую набросы на вентилятор:
«Код на go на 20-30 процентов короче аналогичного на яве (там просто не лишних слов, например, нет точки с запятой в конце каждого предложения, нет круглых скобок в операторах условия или цикла etc)»
Что значит на 20-30% короче? С какой версией сравнивалось? Напомню — лямбды, диамонды позволяют сильно экономить на обязательной выразительности кода. Приведённые же примеры — просто шик! Точка с запятой на конце! Как сложно поставить! Отсутствие скобок на ифе/цикле — опять же вкусовщина. Мне вот скобки нравятся — они визуально помогают выделить блок условия.
«В go очень быстрый компилятор (несколько секунд на компиляцию большого проекта)»
Вообще непонятная фраза. Компилятор в Java тоже очень быстрый. + различные механизмы онлайн подгрузки классов. Нет, если бы была статься "… глазами программиста C++" я бы мог понять… Но Java-то тут причём?
«1) Используя метод пристального взгляда искать в коде неэффективные места, пробовать их исправлять и, после каждого изменения, вновь запускать нагрузочные тесты. Этот способ очевидно неэффективен.»
На !1ом! месте человек рассматривает метод визуального профилиривония… СЕРЬЁЗНО???
«2) Погрузиться в изучение альтернативных серверных библиотек, пробовать разные варианты. Это тоже не дает никаких гарантий — возможно проблемы в моём собственном коде, или вообще в самом языке java.»
Это надо было делать ДО начала написания кода. Потому что с неплохой вероятностью существенный кусок кода будет просто выброшен. И раз уж существующих знаний нужных библиотек нет — это надо было делать ОБЯЗАТЕЛЬНО.
«3) Наконец, я мог купить один или несколько платных профилировщиков и попробовать получить какую-то информацию от них. Но и тут есть проблемы. Если использовать локальный сервер, стоящий у нас в офисе, я не мог создать нужной нагрузки, поскольку у нас в офисе нет нужного количества свободных машин, чтобы запустить несколько тысяч клиентов. Если же использовать внешний сервер, то требовалась довольно сложная конфигурация, чтобы запустить там профилировщик. Наконец, выбор профилировщика сам по себе является нетривиальной задачей.»
Тут сразу несколько шедевров: зачем-то понадобилось покупать профилировщики и пробовать получить информацию от них. Во-первых профилировщиков очень много. И платных и бесплатных. Если человек (программист Java) давно работает в индустрии — ему не надо покупать, необходимый набор у него есть. При этом автор не пожаловался на то, что профилировщики влёгкую могут врать (привет JUG движуха в Питере, которая знает!). Но почему-то пожаловался (кстати, в исходной статье он называл вообще невозможным) на трудности запуска профилировщика на внешнем сервисе. Что ему мешало поднять на своём сервере виртуалку — опять же тайна. Да и просто «сложно создать достаточную нагрузку»… это как? Сервер слишком жирный? Ну так не пускайте за пределы 2х-4х ядер JVM! Да и даже в этом случае — вполне можно было сделать кластер-бота, который легко нужную нагрузку даст. При этом решение с нагрузкой так и не было озвучено. Взяли Go и сразу всё само образовалось?
ну и самое вкусное:
«Go создавался гораздо позже и на сегодня в нем присутствует все, что востребовано сейчас и ничего лишнего.»
Это после жалоб-то на отсутствие механизма исключений («Ужасная — обработка ошибок путем проверки возвращаемого функцией кода.»)?! После жалоб на отсутствие генериков («Плохая — это отсутствие generic-ов.»)?!
Не исповедимы, видимо, не только «пути господни», но и мысли человечьи…
PS корм закончился, больших жирных и зелёных просьба отойти. Готов только к нормальному диалогу.solver
01.08.2016 16:15+6Не смешной совсем. Это реально не смешно.
divan0 Какой-то ярый, непримиримый фанат Go.
Он приплетает все, что угодно в качестве аргументов против тех, кто сомневается в Go.
При чем технических аргументов очень мало. В основном он скатывается на личности и их качества.
При чем эта черта отмечается многими в разных Go тусовках. Такое ощущение, что в Go так принято.
Любой камент против Go вызывает бурную, просто неадекватную реакцию.divan0
01.08.2016 16:27-4Я, наверное, что-то не понимаю, но я написал выше конкретно про то, что оскорблять людей — это неправильно, и строить дискуссию со слов «недоразвитый язык» не имеет смысла. Если вы в этом видите «любой камент», «неадекватную реакцию» и «скатывается на личности», то мы говорим на разных языках.
Если честно, то я очень рад, что почти не общаюсь в русскоязычном сегменте — очень отвык уже от такого уровня общения. Но автор статьи не заслуживает того, чтобы его оскорбляли. Человек поделился опытом, потратил время, написал пост на техническом ресурсе, и вынужден терпеть оскорбления. Со стороны выглядит дико и мне жаль, что здесь это норма. Мы люди, пишем софт для людей, мы можем находить общий язык, если соблюдать простые базовые правила общения. Во всем мире это работает, кроме рунета.
Iora
01.08.2016 16:36+4Где-то высказывали мнение, что это во многом из-за того, что Go был создан в Google Робом Пайком. И тут сложились два фактора: все, что делает «корпорация добра» по-умолчанию идеально, и всё, что делает такой человек, как Пайк — тоже идеально и все архитектурные решения, сколь бы нетрадиционными они ни были, по-умолчанию не могут быть подвержены критике из-за личности автора (если почитаете другие комментарии этого товарища, то там часто встречается что-то вроде «вы еще Пайка поучите», «Пайк знает, как правильно» и так далее).
Нет, Go выглядит довольно интересно и то, что он так бурно развивается — хорошо. Но уж больно его фанаты… фанатичны.
grossws
30.07.2016 02:14+4Профилировщики, которые я видел, требуют, чтобы их запускали на той же машине, что и сервер.
JMC и VisualVM умеют подключаться к приложению по tcp. YourKit умеет подключаться удаленно. Какие профайлеры вы видели (и читали документацию к ним, ессно)?
softaria
30.07.2016 08:49-4Неаккуатно написал. Имел ввиду существенно различную сложность при использовании профайлеров java и go.
grossws
30.07.2016 02:19+15Сначала для многозадачных приложений в языках программирования были придуманы процессы.
А за такое автора хочется бить тапком. Процессы — это сущность уровня ОС, они существуют не в языках программирования. То, что из ЯП можно дернуть соответствующий syscall (или библиотечную функцию) для порождения процесса не означает, что они "придуманы в языках программирования".
Lure_of_Chaos
30.07.2016 02:43Я думаю, это надо понимать так: сначала для многозадачных приложений приходилось использовать процессы уровня ОС, дергая соответствующий системный вызов.
grossws
30.07.2016 02:51Для создания треда в linux, например, обычно дергается syscall
clone
, если правильно помню. Создание нового процесса может выпоняться им же, просто с другими флагами, касающимися выделения нового стека, адресного пространства и т. п. Принципиального отличия с точки зрения ядра нет.
Основной недостаток использования процессов — более дорогой IPC (хотя иногда выкручиваются через
/dev/shm
) по сравнению с использованием общей памяти разными потоками в рамках единого адресного пространства.
Ckpyt
30.07.2016 05:09+1Автор!!! 300 клиентов на сервер!!! Вот это да!!!
На плюсах писал сервер для ММОРПГ мне в страшном сне не могло такое присниться… минимум 10 000 при использовании самых жестких процедур
.
А хотите а скажу как можно создать эмулятор ЛЮБОГО количества клиентов на ОДНОМ клиенте?
Берете вайршарк, пишете пакеты(еще лучше, свой сниффер), запускаете клиент, делаете нужные действия, пишете пакеты.
А потом те же пакеты размножаете любым доступным способом. Вплоть до забивания пропускного канала :-) Так как вы автор, вы знаете где у вас в пакете хранятся уникальные для каждого пакета id и знаете как легко их можно поменять. Так что — это реально легко и просто :-)
Почему свой сниффер лучше — понятно?
Дайте, я еще угадаю: положение игроков рассылается не каждому по запросу, а от каждого каждому? В смысле, пришел пакет на изменение положения, это изменение разослали всем в зоне?
П.с. это не в смысле «блин… какой дурак», а в плане «ооо!!! И я таким же молодым был» :-)webmasterx
30.07.2016 06:12В смысле, пришел пакет на изменение положения, это изменение разослали всем в зоне?
А как правильно? игры ни разу не делалCkpyt
30.07.2016 07:31У нас было так — в зоне храниться лог обработанных событий за последнюю минуту(т.е. не юзер2 жмет влево, а персонаж такой-то изменяет координаты на столько-то). Приходит пакет и говорит: «я хочу лог зоны с такой-то секунды и такой-то миллисекунды». Ему в ответ: «вот тебе родной», и сервером передается лог событий. Клиент, соответственно, запрашивает состояние зоны каждый раз, как поймал ответ, но не чаще чем через 250 мс от отправки предыдущего пакета, и не реже чем раз в четыре секунды(udp-пакеты могут теряться). Т.е. что пинг 50, что пинг 250 — без разницы.
Почему это лучше? Потому что у клиента пинг может достигать до трех-четырех секунд… и он все равно будет видеть все, что происходило.
У нас время жизни клиента без ответа было 15 секунд. Т.е. если от клиента не было ни одного пакета за 15 секунд, он вышел и должен заново проходить авторизацию. Этого хватало на самые плохие пинги(вроде, на Камчатке был клиент, но сейчас уже не уверен, где-то в дальних гребенях со стабильным пингом в три секунды).
При этом, когда идет рассылка любых изменений всем в зоне, количество пакетов растет квадратично в зависимости от количества клиентов.softaria
30.07.2016 08:27Как вы представляете многопользовательский шутер с временем жизни клиента без ответа в 15 секунд?
Ckpyt
30.07.2016 09:25А что вы делаете, если от пользователя перестали приходить пакеты, но корректно он не вышел?
За 15 секунд пользователь, если у него проблемы, успевает перезагрузиться и снова запустить клиент.
И да, его за это время могут даже не убить. Если он успел заныкаться или находится на стартовой позиции.softaria
30.07.2016 09:29Если от него перестали приходить пакеты, его коннект убивается сервером (примерно, через секунду)
Думаю, наши игры очень разные. Моя больше всего похожа на agar.io/slither.io.
Там всё очень быстро происходит. 15 секунд — неприемлемо огромный интервал
Vest
31.07.2016 12:31+1Позвольте спросить у вас, почему вы выбрали способ именно «пересылки/повторении» трафика на свой сервер?
Ведь наверняка при планировании архитектуры игры, вы могли бы заранее создать инструменты генерирующие эти самые запросы. Например, клиент использует некоторую библиотеку, которая отправляет/принимает запросы, потом её подготовить (можно урезать), и после вызывать нужные методы в большом количестве и с нужными параметрами.
На мой взгляд, трафик записанный Wireshark оказывается не параметризованным, тем самым порождая кучу проблем: все пользователи находятся в одинаковых координатах, двигаются в одинаковом направлении и т.д.
Спасибо за ответ.Ckpyt
01.08.2016 21:34+1Во-первых, судя по статье, я подумал, что автор не очень опытный разработчик. И потому я посоветовал самый просто способ. Ну, на мой взгляд :-)
Во-вторых, исследование СВОЕГО трафика — это одна из вещей, которой нужно заниматься при оптимизации клиента, о которой мало кто помнит.
В-третьих, инструмент генерации пакетов так же нуждается в поддержке. Я понимаю, что в идеале правильнее всего было бы сделать «идеального бота» — выбирающего рандомные направления и жмущего рандомные кнопки из числа осознанных комбинаций. И соответственно, советовать писать его с нуля молодому(как я думал) программисту — не надо.
Ну и в-последних: описанная мною фигнулька пишется часа за два-три в худшем случае… А вот с пакетогенераторам придется повозиться.
Вот где-то так вот.
Bringoff
30.07.2016 08:07+12Что я понял из статьи: "Мне было нечем заняться, так что я решил выбросить шмат работы и переписать сервер на Go, потому что там есть встроенный профилировщик".
Изначально у вас на Go получилось 20 клиентов, после профилирования 2500, то есть, на минутку, в 125 раз (!) больше.
Вы не думали, что осиль вы профилировщик на джаве, у вас бы могло выйти ~37500 клиентов? Ну, или даже если бы вышло 2500, что всего в 8 раз больше первоначального (с таким размахом в Go-коде я не удивился бы), усилий пришлось бы приложить заметно меньше.
Да, никогда от хороших java-разработчиков не слышал "ява".softaria
30.07.2016 08:31-2Что я хотел сказать статьёй. «Написание определенных приложений занимает на go в несколько раз меньше времени и усилий чем на java. В том числе за счет более удобных инструментов.»
sentyaev
30.07.2016 23:58+2Я считаю это больше зависит от опыта и знания платформы. Т.к. по сути Go и Java языки одного уровня. Понятно, что на Go писать веб-сервер удобнее чем на Assembler.
А то, что встроены инструменты или нет, это уже не имеет большого значения.softaria
31.07.2016 14:44-1Согласился бы. Но вот на java я пишу 18 лет, а на go к тому моменту не писал вообще.
Но на go таки вышло быстрее. Причем очень существенно.sentyaev
31.07.2016 15:22+2Так именно это и вызывает сомнения.
Вот например у меня чуть больше 10 лет опыта в .NET, и как-бы мне ни нравился какой-либо новый язык, я не могу быть на нем продуктивным. Т.к. дело-то не в языке, а в платформе, экосистеме, библиотеках и доступных инструментах, плюс мой опыт и знание всего этого.
Я все это время занимаюсь веб-разработкой, причем примерно 90/10 если говорить backend/frontend, так даже по прошествии 10 лет я не могу сказать, что я хороший фротэндер (хотя последние пол года делаю проект на Angular2, и думаю еще через пол года, год у меня будет очень хороший уровень).
Не важно какой язык выбрать (C#, Java, Python, Kotlin, Go и т.д, я имею ввиду языки одного уровня), важны ваши знания того, что сформировалось вокруг этого языка/платформы.
Я хочу подчеркнуть, не язык вас делает продуктивным, а опыт и знания, и не только ваши, а еще и тех людей которые потратили годы для развития «экосистемы».softaria
31.07.2016 15:28-4Продуктивность складывается из вашего опыта и знаний и удобства и мощности языка (в том числе, применительно к конкретной задаче).
Это легко можно увидеть на примере — человек X потратил много лет на изучение ассемблера.
У него стоит задача написания веб сайта.
Что будет для него эффективнее — писать сайт на ассемблере или на .NET?
Я думаю, .NET будет лучшим выбором.
Здесь я столкнулся с похожей ситуацией — увидел класс задач, который решается на go настолько удобнее, что несмотря на мой опыт на java я теперь предпочитаю для таких задач go.sentyaev
31.07.2016 16:10+1Это легко можно увидеть на примере — человек X потратил много лет на изучение ассемблера.
У него стоит задача написания веб сайта.
Это понятно, и про это я уже писал. Но Go и Java суть одно и тоже, просто синтаксис разный.
Просто все ваши ответы на вопрос «Чем же Go лучше», вы отвечаете «Лучше чем другие языки». Согласитесь, что это сомнительный аргумент.
В свою очередь хочу заметить, что ходить в джинсах синего цвета гораздо удобнее, чем в красных)))softaria
31.07.2016 18:13Но Go и Java суть одно и тоже, просто синтаксис разный.
Не соглашусь. Иначе не было бы смысла вообще создавать go.
Каждый язык имеет свои сильные и слабые стороны. Один хорош для одних целей, другой предпочтительнее для других. Каждый имеет свою нишу.sentyaev
31.07.2016 19:46Вообщето, вопрос «зачем было создавать Go» не стоит.
Why are you creating a new language?
Go was born out of frustration with existing languages and environments for systems programming…
Go is a programming language designed by Google to help solve Google's problems, and Google has big problems. Полный текст тут.
Просто Google нужен был свой. Чтобы решать свои задачи.
Я считаю, что у Go, Java, C#, Python, Ruby почти одна и таже ниша.
Могли бы вы привести конкретный пример, в решении какой задачи Go так продуктивнее Java?
Здесь я столкнулся с похожей ситуацией — увидел класс задач, который решается на go настолько удобнее, что несмотря на мой опыт на java я теперь предпочитаю для таких задач go.
Мне бы хотелось понять, что это за задачи.
Т.к. в вашей статье есть раздел «Инструменты повышения производительности», и указаны там только профилировщик и race detector.
Согласитесь, что в Java таких инструментов предостаточно?softaria
31.07.2016 19:59+1Просто Google нужен был свой. Чтобы решать свои задачи.
Из этого можно сделать вывод, что есть какие-то задачи, для которых go подходит лучше других языков. (Ну или, что google таки создал его зря, как следует не разобравшись).
А раз так, значит go отличается от других не только синтаксисом.
Мне бы хотелось понять, что это за задачи.
Цитирую свою же статью: Какие задачи лучше всего решать на go? Создание многопоточных высоконагруженных серверных решений, в которых потоки много коммуницируют между собой.
Согласитесь, что в Java таких инструментов предостаточно?
Соглашусь. Предостаточно. Здесь речь скорее о философии языка. О том, что с точки зрения того или иного языка важно (а значит включено в набор стандартных инструментов, хорошо продумано и документировано) или просто есть (и, чаще всего создано третьими сторонами).
На любом современном языке можно сделать всё что угодно.
Разница в том, на чем язык предлагает сосредоточиться в первую очередь. В go профилирование и борьба с race conditions это, если хотите — first class citizens. В java — просто часть огромной экосистемы.iqiaqqivik
01.08.2016 08:05+1> Из этого можно сделать вывод, что есть какие-то задачи, для которых go подходит лучше других языков
Абсолютно корректный вывод. Такая задача одна, и эта задача — упростить найм (Гугл нанимает так много сотрудников, что профессионалов в этих количествах взять просто неоткуда). Иными словами вот таких «я тут потыркался в java, что-то не взлетело, ну так сейчас перепишем на го и заживем». Го спроектирован таким образом, чтобы даже баран не мог сильно напортачить, и это — его единственная цель (и плюс).
Сеньор в _любом_ другом языке решит _любую_ задачу лучше, чем на го. Джуниор на го решит любую задачу лучше, потому что ему язык надает по рукам в нужных местах. Но за все нужно платить: пока у вас не пятьсот тысяч сотрудников, го — обуза.
firsttimecxx
31.07.2016 17:15+4>>Что будет для него эффективнее — писать сайт на ассемблере или на .NET?
Подмена понятий.
>>Я думаю, .NET будет лучшим выбором.
Не верно, ибо подмена понятий.
Никто не пишет сайты на .net. Никто не пишет сайты на языке — сайты пишут на готовом апи. И без разницы какой это язык, если ты вызываешь какой-нибудь интерфейс. Разница только в сахаре, но это не особо принципиально, да в современных ассемблерах сахара не меньше.
Подлог заключается в том, что вы сравниваете пацана с .net, который на 99% состоит из готового веб-рантайма и пацана с асм, у которого рантайма нет. Но ведь .net-пацан этот рантайм не писал — точно так же асм-пацан может его написать, либо взять готовое.
Если же взять нормальное сравнение, а не изначально ущербное, то никакой разницы не будет.
Реальный мир просто способствует продвижению этого мифа, ибо задачи на тех же сях решаются дольше. Но это следствие не того, что на сях «дольше», а просто задачи решаемые на сях сложнее. Живые сравнение Си вс жава не проводятся, ибо это не имеет смысла.softaria
31.07.2016 18:15Это не подмена понятий а иллюстрация явления в его крайней форме.
А само явление заключается в том, что есть много языков программирования и раз каждый жив, значит у него есть ниша, где он лучше других.firsttimecxx
31.07.2016 21:50+3В любой форме это сравнение не имеет смысла, ибо не является правдивым. Чистейшей воды подмена понятий «средства языка» с «готовые средства рантайма для реализации какого-то функционала». В данном случае в .net средства для веб есть по умолчанию, а у асм«а нет. И средства эти не уровня языка.
Сам же язык — это про удобство использования api и в редких случая для написания нового кода, но там кроме циклов и функций ничего нового особо не придумали.
А далее уже удобство использования самого языка и чьи-то синтаксические предпочтения. Кому-то нравится $i, а кому-то нет. Кому-то нравится экосистема одного языка, а кому-то другого. В целом при равной мощи рантайма разница между языками в „запилить быстро и удобно“ мало различима.
>>значит у него есть ниша, где он лучше других.
Скорее наличие ниши и делает язык лучше, ибо он более специализирован, а не наоборот. И то не сам язык(в очень маленькой степени), а его рантайм/реализацию самого языка.
Лучше в смысле как язык, то тут не всё так просто. Лучше в одном — хуже в другом.
sentyaev
01.08.2016 02:32Конечно подмена понятий, я изначально написал несколькими комментариями выше:
Я считаю это больше зависит от опыта и знания платформы. Т.к. по сути Go и Java языки одного уровня. Понятно, что на Go писать веб-сервер удобнее чем на Assembler.
Slepetc
31.07.2016 23:54+1Очень спорный аргумент. Перевести приложение с одного языка на другой почти всегда проще, чем писать его с нуля.
alexkran
30.07.2016 08:31Интересная статья, спасибо.
Довольно адекватно расписаны возможности языка. Однако Go для совсем новичков я бы никогда не рекомендовал, учиться программировать на Go гораздо тяжелее, чем на Java, в силу того, для чего он разрабатывался и какие задачи должен выполнять, имхо.divan0
31.07.2016 15:52+1Однако Go для совсем новичков я бы никогда не рекомендовал, учиться программировать на Go гораздо тяжелее, чем на Java
Можно тут чуть подробнее? Почему «гораздо тяжелее»? Давно интересуюсь темой Go как первого языка программирования, и интересны мнения со стороны.SirEdvin
31.07.2016 18:46Go не прививает, скажем, правильное ООП, и подвержен некоторым крайне сомнительным практикам, например, хранение метаданных в комментариях или кодогенерации.
divan0
01.08.2016 09:41-4правильное ООП
Что это такое? И почему «неправильное ООП» сложнее новичкам, чем «правильное ООП».
крайне сомнительным практикам, например, хранение метаданных в комментариях или кодогенерации.
Принимаю аргумент про «сомнительные практики» — в других языках это действительно были хаки и сомнительные практики, но в чём проблема у новичков с этим?
SirEdvin
02.08.2016 08:16Что это такое? И почему «неправильное ООП» сложнее новичкам, чем «правильное ООП».
Скажу проше. В Go — нет ООП. Go — это процедурный язык. И то, что в Go можно писать в ООП-стиле не делает его OOP языком. Аналогичная ситуация в Java, никто не назовет Java функциональным языком, но писать в таком стиле там можно. А как показывает практика, процедурников крайне сложно научить потом ООП.
Принимаю аргумент про «сомнительные практики» — в других языках это действительно были хаки и сомнительные практики, но в чём проблема у новичков с этим?
Мое мнение, что первый язык программирования должен давать как понимание и программировании в целом, так и о типичных практиках, которые используются в множестве других языков. В такой точки зрения очевидно, что такой язык как Go, который довольно сильно выбивается из ряда стандартных языков не дает такой картины.
iqiaqqivik
02.08.2016 09:39> как показывает практика, процедурников крайне сложно научить потом ООП
То есть, история вопроса нам как бы сообщает: в семидесятые годы прошлого века, когда мир вокруг состоял сплошь из процедурников, к нам явились марсиане и научили ООП. Так?
SirEdvin
02.08.2016 12:50-2Крайне сложно — не значит, невозможно.
К тому же, в семидесятые годы были еще и фунциональщики или даже странные люди, которые страдали логическим программированием.
Falstaff
02.08.2016 09:55+2Справедливости ради, Алан Кей изначально вроде бы не думал о полиморфизме и наследовании как неотъемлемых свойствах ООП. Тема довольно размытая, поэтому категорично утверждать, что в каком-то языке нет ООП, а в другом есть — вряд ли конструктивно. Думаю, что «сильно отличается от повсеместно используемых практик» это максимум, что можно сказать, не рискуя уйти в холивар.
Вообще, есть ли смысл абсолютных новичков учить объектно-ориентированной парадигме? Если говорить вот прямо о людях с улицы, без курса CS за плечами, без какой-то IT основы. Мне кажется, что они будут тяготеть к процедурному стилю, обрушить на них объекты или функциональное программирования — у них сразу интерес пропадёт.
SirEdvin
02.08.2016 13:00-1Вообще, есть ли смысл абсолютных новичков учить объектно-ориентированной парадигме?
Смысл есть, так как 70-100% задач на рынке решается именно через ООП, потому что оно туда как раз и подходит. Скажем, я сталкивался с тем, что люди, которые много пишут в процедурном стиле не понимают, зачем им нужно вообще это ООП и получается их заставить его учить только поставить или довольно исскуственную задачу, в которой сложно обойтись без принципов ООП, или закинуть его в реальный проект, но это вызовет большие пробелы в дальнейшем.
Справедливости ради, Алан Кей изначально вроде бы не думал о полиморфизме и наследовании как неотъемлемых свойствах ООП.
Википедия, с ссылкой на книгу Т. Бадда (isbn 5887822708 в русском переводе) дает такой список правил, которые оговаривал Алан Кей:
- Всё является объектом.
- Вычисления осуществляются путём взаимодействия (обмена данными) между объектами, при котором один объект требует, чтобы другой объект выполнил некоторое действие. Объекты взаимодействуют, посылая и получая сообщения. Сообщение — это запрос на выполнение действия, дополненный набором аргументов, которые могут понадобиться при выполнении действия.
- Каждый объект имеет независимую память, которая состоит из других объектов.
- Каждый объект является представителем класса, который выражает общие свойства объектов (таких, как целые числа или списки).
- В классе задаётся поведение (функциональность) объекта. Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия.
- Классы организованы в единую древовидную структуру с общим корнем, называемую иерархией наследования. Память и поведение, связанное с экземплярами определённого класса, автоматически доступны любому классу, расположенному ниже в иерархическом дереве.
Тут есть наследование.
iqiaqqivik
02.08.2016 13:55+1В чем принципиальная проблема нагуглить первоисточник, вместо каких-то «Вика сказала, что Бадд написал»?
? http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
? http://www.c2.com/cgi/wiki?AlanKaysDefinitionOfObjectOriented
Не было там ни полиморфизма, ни наследования.SirEdvin
02.08.2016 14:18Очевидно, от глупости, лени и не хватки времени.
Большое спасибо за первоисточник :)
Falstaff
02.08.2016 14:36С практической точки зрения — да, мотивация понятна: чтобы потом не переучивать для боевых задач. Я скорее говорю о ситуациии с людьми, которых в любом случае ещё рано закидывать в реальный проект — не интернов или джуниоров, а, скажем, детей, или просто впервые осваивающих программирование. Любопытно, есть ли тут кто-нибудь, кто детям преподавал. У меня очень маленький с этим опыт, будет нерепрезентативно.
Idot
02.08.2016 14:50Детский Scratch — учит Объектно-Ориентированному Программированию.
Детский Logo — учит Функциональному Программированию.
— и то и другое дети вполне понимают.Falstaff
02.08.2016 15:05Лого вроде мультипарадигменный, нет? Тут скорее интерес с точки зрения опыта. Scratch — да, хороший пример.
softaria
31.07.2016 18:36Я правильно понимаю, что у вас был опыт наблюдения за новичком, который пытался начинать с go?
Если это так, расскажите подробнее, пожалуйста.
Я никаких проблем не вижу, но поскольку к моменту изучения go новичком не был, то мог что-то важное пропустить.
А вопрос для меня, действительно важный — думаю о более широком применении go в нашей компании.
В том числе и для юниоров.sentyaev
31.07.2016 20:36Есть небольшой опыт обучения совсем новичка в программировании. Сначала выбрали Go, но как-то сразу не пошло (я не говорю, что я очень хороший учитель, но очень старался).
Начали с самых основ, без языка по сути. Рассказал основы, порисовал немного. Вроде бы можно было приступать к первым шагам.
Долго продвигались через такие понятия как переменная и функция.
Первой же большой проблемой стало объявление переменных в Go и два варианта присваивания (это для начала решили пропустить и взяли только один вариант).
Когда дошли до структур, столкнулись с тем, что человек не понимал как их создавать. Попытки объяснить проблему не решали.
С методами было совсем плохо, просто было не возможно объяснить разницу между обычной функцией и методом.
Про интерфейсы я совсем молчу.
Через месяц решили не мучатся.
Расчехлили Java, и буквально на второй день человек освоил классы, методы, и принципы ООП. Даже по глазам стало видно, что товарищь теперь все понимает, а не «тупит». Ну, вы же знаете этот горящий взгляд и желание быстрее что-нить накодить.
Такой вот опыт.
И мне кажется успех ООП как раз в этом, его понимают обычные люди.softaria
31.07.2016 20:47Спасибо. Интересный опыт. Хотя, данных для статистики недостаточно.
Вдруг это — особенность конкретного человека.sentyaev
31.07.2016 21:01Согласен, один человек — выборка недостаточная.
С другой стороны этот самый человек очень хорошо усваивает программирование, и, на начальном этапе, проблемы были именно с «философией Go» и его концепциями.
Мне лично, Go тоже показался не самым простым языком. Т.е. первым я бы его точно не смог осилить.
Ну и если почитать Роба Пайка и посмотреть его выступленя, становится понятно, что он человек очень спицефичный. Мне показалось, что ему гораздо важнее решить задачу правильно, чем решить задачу в принципе.softaria
31.07.2016 21:06Мне Go показался простым. Хотя привлёк не этим, а сдвигом «фокуса». Его авторы переосмыслили, что сегодня является важным в языке, а что — не очень. на мой взгляд, их вариант лучше подходит для решения актуальных задач.
А вот смог бы я осилить Go первым или нет — фиг его знает. Именно поэтому очень инетересен опыт тех, кто пробовал.
ему гораздо важнее решить задачу правильно, чем решить задачу в принципе.
Проблема в том, что у каждого своё — «правильно».
alexkran
01.08.2016 11:44Для новичков будут проблемы в понятии самой концепции языка, не каждый новичок поймет как правильно выстраивать структуру приложения из интерфейсов и структур(хотя по мне так прикольная концепция вышла из этого). Потом Go-рутины, для новичка многопоточность это вообще страшная штука, которую просто так не понять с пары примеров, это куча опыта, которую и за год много не накопишь, новички не поймут пользы от многопоточности, Go-рутин, каналов и etc.
И приподносится этот материал по странному. В плане если в Java/C#/C++, когда разговор доходит о многопоточности первым делом говорится для чего это нужно и когда используется, в Go же это одна из основных концепций, и тем самым для совсем новичков это осложняет дело еще сильнее.
Плюс еще ограниченность в плане, как бы правильней сказать, видимости результата. Новичкам нужно видеть, как у них в программе банально произошли вычисления и они вывелись на экран, особенно все начинающие любят GUI и формочки, для чего Go не очень адаптирован, хоть и может. А если же язык показывает какие-то вещи, которые еще не дошли до молодого ума и он не видит результата то это веет смуту.
Если у человека есть опыт программирования даже просто в плане обучения на каком-нибудь Ruby/Python/Java, ему будет в этом разобраться будет не так уже тяжелее. Имел опыт общения с Go после C++, и в целом неплохо.
Go в целом язык ничего так, но не прям уж для запихивания во все дырки и не для совсем новичков. Это лично мое мнение.
dimkss
30.07.2016 08:31-3Спасибо за четкую, и по делу статью.
Как вы думаете, Go ориентирован только на серверное использование, или на нем можно забацать приложение с окнами, графикой, и еще какими то финтифлюшками?
Agonee
30.07.2016 08:33+5Открой для себя JNI
softaria
30.07.2016 08:33+1Зачем?
Agonee
31.07.2016 07:40Перформанс. Статья ведь об этом.
firsttimecxx
31.07.2016 14:44Но ведь это не жава? С таким же успехом можно писать на си и вызывать из го, не?
IllusionTurtle
30.07.2016 09:36Для решения этой проблемы используются внешние инструменты — менеджеры пакетов.
Один из лучших на сегодняшний день — glide.
Зачем использовать стороннюю утилиту, если данная проблема уже решена на уровне языка — используйте директорию vendor (v1.5 experimental, v1.6 default)
Кстати, директория vendor решила и ещё одну проблему о которой вы не упомянули, локальные импорты.softaria
30.07.2016 09:37glide её использует
Просто он позволяет не хранить сторонние пакеты в своей системе контроля версий.
Каждый член команды может при помощи glide поместить в свою директорию vendor нужные версии сторонних пакетов.
naething
30.07.2016 09:38+8Судя по приведенным аргументам, все-таки остается впечатление, что выбор сделали скорее эмоциональный, нежели рациональный. Новый язык всегда изучать весело.
Если требуется поддерживать несколько тысяч клиентов одновременно, особенно при высокой частоте запросов как в онлайн игре, понятно что скорее всего придется использовать асинхронный ввод-вывод вместо традиционной модели «один поток на соединение». Тут, как говорится, и к гадалке (профайлеру) не ходи. Да, в Го это работает из коробки путем использования «горутин», ну а в Java можно использовать Netty.
Проблема с запуском профилировщика удаленно в Java совершенно надумана. Достигается добавлением пары опций в JVM.
Проблема с запуском нескольких тысяч клиентов тоже надумана. Зачем запускать настоящие клиенты, если можно с помощью того же Netty/NIO написать относительно несложную программу для нагрузочного тестирования, которая буквально с одного компьютера создаст достаточную нагрузку?
И в конце концов, в Го вы все равно можете упереться в сборщик мусора или, скажем, странное поведение планировщика горутин. И что тогда, снова все бросить и переписать на C++?
По-моему, шило на мыло. Выбросили существующий код и проверенную временем JVM ради «модного» языка из-за каких-то странных доводов.softaria
30.07.2016 09:50-4> а в Java можно использовать Netty.
Или VertX или Play или много чего еще.
> Проблема с запуском профилировщика удаленно в Java совершенно надумана.
Тут вы правы. Я неверно расставил акценты. На самом деле надо было сказать о простоте и удобстве работы со штатным профилировщиком go. По мощности он превосходит VisualVM и сравним с YourKit. По удобсвту работы — лучшее, что я видел вообще. Экономит много времени.
> написать относительно несложную программу для нагрузочного тестирования
Я её и имел ввиду. Только она не могла быть совсем уж несложной. Нужно было эмулировать все кейсы, чтобы убедиться, что дикие утечки памяти не возникнут, скажем, при телепортации или еще в каком неожиданном месте.
> в Го вы все равно можете упереться в сборщик мусора
Да. Его пришлось отключить вовсе. Точнее перевести в ручной режим. Сначала код был переписан так, чтобы минимизировать использование кучи. Потом автоматический gc был отключен и заменен на код, который запускает его вручную, если свободной памяти на сервере осталось немного. Перед таким ручным запуском все клиенты принудительно ставятся на паузу. Происходит это редко и для игрока такое поведение много луше частых небольших лагов.
> Выбросили существующий код и проверенную временем JVM ради «модного» языка из-за каких-то странных доводов.
Ради опыта. Я знал сколько времени занимает решение подобной задачи на java. Я подозревал, что на go потребуется меньше. Я убедился, что да, меньше. Раза в два. И теперь я буду решать такие задачи на go и экономить свое время.
Этим вот опытом и поделился.naething
30.07.2016 10:20+7Или VertX или Play или много чего еще.
Ну странно наличие вариантов рассматривать как минус. Так же можно было вместо Го использовать Rust, node.js или много еще чего.
Я подозревал, что на go потребуется меньше. Я убедился, что да, меньше. Раза в два.
Верю с трудом, особенно в долгосрочной перспективе, и тем более если есть опыт подобных проектов на Java.
Может быть вы и правы. И даже если выбор эмоциональный, то всегда хорошо, когда программирование приносит удовольствие. Особенно если проект небольшой и делается в основном на энтузиазме.softaria
30.07.2016 10:35-2Ну странно наличие вариантов рассматривать как минус.
Наличие вариантов имеет свои минусы (порог вхождения) и плюсы (можно подобрать наиболее оптимальный).
Если говорить о продуктивности разработки, то наличие ровно одного хорошего способа сделать что-то будет плюсом, так как сэкономит время.
Верю с трудом, особенно в долгосрочной перспективе, и тем более если есть опыт подобных проектов на Java
Здесь сложно что-то возразить. У меня оно было так. Но каков в этом результате вес самого языка, моего проекта и моих личных предпочтений мне сказать трудно. Если есть опыт разработки таких проектов на java и если вас не раздражают VisualVM или YourKit, то, возможно, у вас будет другой результат.
Единственное, на чем я настаиваю — если взять двух новичков и один станет изучать java + экосистему, а второй go, то проект, подобный моему, быстрее получится у второго при прочих равных.Suvitruf
30.07.2016 11:03+2Наличие вариантов имеет свои минусы (порог вхождения) и плюсы (можно подобрать наиболее оптимальный).
Отсутствие альтернатив во все времена приводило к монополии. Наличие конкурентов/альтернатив вынуждает авторов библиотек совершенствовать свои продукты.
Если говорить о продуктивности разработки, то наличие ровно одного хорошего способа сделать что-то будет плюсом, так как сэкономит время.
Единственное, на чем я настаиваю — если взять двух новичков и один станет изучать java + экосистему, а второй go, то проект, подобный моему, быстрее получится у второго при прочих равных.
А если взять профессионала, то тот выберет java, так как на ней лучше писать долгоживущие проекты?softaria
30.07.2016 11:37-1Отсутствие альтернатив во все времена приводило к монополии. Наличие конкурентов/альтернатив вынуждает авторов библиотек совершенствовать свои продукты.
Вы привели еще один плюс наличия альтернатив. Только он не имеет отношения к продуктивности разработчика здесь и сейчас.
А если взять профессионала, то тот выберет java, так как на ней лучше писать долгоживущие проекты?
А если взять профессионала, тот изучит проект и будет выбирать инструмент исходя из требований.
ShadowsMind
30.07.2016 10:39+8«я слепил чего-то там на java и оно держало всего 300 коннектов, переписал на go — стало держать 2.5к» (с)
Ничего не имею против Go, но давайте поговорим о Ваших опытах с Java.
Есть куча суццесс стори задач схожих с вашей — сверера для мультиплеерных игр. Возьмем на пример Riot Games и их League of Legends, где на секундочку, онлайн в пики достигает 5 миллионов юзеров. Понятное дело там у них маштабирование и прочее, но если бы у них сервер держал 300 коннектов, то никаких денег бы не хватило, будь Ваши слова хотя бы отчасти правдой.
Если уж Вы пытаетесь продвинуть мысль того, что go производительнее java в разрезе вашей задачи, то пишите подробности реализации, сравнения, бенчмарки в конце концов. Насколько мне известно, Netty вообще одна из самых производительных штук в разрезе данного юзкейса и сдается мне, что Вы либо писали свои костыли либо просто не умеете в Netty…
Из всей статьи полезный и осмысленный только вывод…softaria
30.07.2016 10:41+1Если уж Вы пытаетесь продвинуть мысль того, что go производительнее java в разрезе вашей задачи
Вы неправильно поняли. В разрезе моей задачи производительнее не go, а программист, пишущий на go.
Он справится с такой задачей быстрее, даже если ранее имел опыт программирования на java и не имел на go.ShadowsMind
30.07.2016 10:58+2Т.е. в конторах пишущих игры ААА класса сидят дурачки, которые не знают, о том что программист на Go производительнее программиста на Java?! Тогда уж «в разразе Вашей задачи Вы пишущий на Go произовдительнее себя же пишущего на Java».
softaria
30.07.2016 11:11Т.е. в конторах пишущих игры ААА класса сидят дурачки, которые не знают, о том что программист на Go производительнее программиста на Java?!
Нет. Там сидят большие сложившиеся команды, которые много лет пишут на java и имеяют массу наработок, которые переиспользуются в новых проектах. Для них стоимость перехода на другой язык огромна.
в разразе Вашей задачи Вы пишущий на Go произовдительнее себя же пишущего на Java
Если говорить совем строго, то да. Именно так. Но я рискну расширить это утверждение до следующего «в разразе моей задачи человек с 18летним опытом программирования на java и нулевым опытом на Go, пишущий на Go произовдительнее себя же пишущего на Java»fogone
30.07.2016 12:20+11человек, который 18 лет разрабатывает на java и не знает о существовании возможности удаленного подключения профилировщика, вызывает подозрения
DragonFire
30.07.2016 12:29-2Вы то точно разрабатываете на java со вчера и уже знаете абсолютно все, мы не сомневаемся =)
fogone
30.07.2016 14:55+2Сомнения — признак критического мышления, а то, в свою очередь, признак здравомыслия
softaria
30.07.2016 12:29Вы правы. Не пойму, как я написал такое. На эмоциях, наверное. Очень раздражает меня VisualVM. Трудно найти что-то более неудобное.
fogone
30.07.2016 15:09+3Согласен с тем, что не всё в мире java идеально и в эпоху перемен хочется свежего воздуха, я и сам внимательно смотрю на котлин. Здорово, что этот глоток свежего воздуха пришелся вам по душе, но все-таки статья скорее эмоциональный выплеск об этом, нежели что-то полезное в техническом смысле. Было бы интереснее, если бы вы описали какие аналогичные средства вы использовали в обоих реализациях и что именно было удобнее, возможно рассказать об архитектуре серверной части игры, а такой холиварный формат неизбежно вызывает раздражение у читающих
softaria
30.07.2016 17:41-1Это всё от лени. Я просто взял и опубликовал собственный рассказ на корпоративном семинаре.
По уму для хабра статью надо было перделать и писать примерно так: Вот уже 14 лет мы пробуем новые языки, чтобы не пропустить технологическую волну. До сих пор, ни один язык не выигрывал у явы в главном для нас параметре — в скорости разработки. Так было, пока не появился go.
Этот самый go выиграл по этому параметру на таком-то проекте. Если ваш проект похож, обратите внимание на go.
Тогда бы и холивара было бы поменьше.solver
30.07.2016 20:07+7Холивара было бы поменьше, если такие статьи (саксес стори) по Go были более объективными.
А так они все как под копирку. Одни досужие домыслы и притягивания за уши. Без какой либо конкретики.
Добавьте сюда, по вкусу: вранье, передергивание или откровенное нубство в сравниваемой технологии (в данной статье про Java).
И получите типичный холивар.
Напишите нормальную статью. С примерами похожих задач.
Вот так делали на Java (и это должен быть реальный пример на современных подходах и библиотеках).
А вот так мы сейчас делаем на модном Go.
С описанием и цифрами. Что улучшилось в процессах. Что улучшилось в коде. Что там с багами и поддержкой. Что с рефакторингом и т.д.
Все вам огромное спасибо скажут.
А то вот таких вот домыслов «вилами по воде» в каждом бложике миллион.
Они ничего не улучшают, а только хуже делают.
Ибо оставляют больше вопросов, чем дают ответов.
А в отсутствии реальных фактов, люди начинают сплетничать и фантазировать на тему как оно там может быть…softaria
30.07.2016 21:31-1Вы пишите о вранье, передергивании и нубстве и тут же требуете цифр, примеров и фактов.
Допустим я скажу, что аналогичная задача на яве заняла у меня X дней, а на go — Y (где Y<X), вас это убедит?
На самом деле, каждый приведенный факт можно поставить под сомнение. Кажды новый факт будет лишь разжигать холивар.
Проблема совсем не в фактах, а в неаккуратном позиционировании моей статьи. Многие тут посчитали, что я хвалю go и ругаю java, приводя в качестве (слабого) аргумента некую сомнительную, как вы сказали «success story». Я сам дал повод так понять эту статью неаккуратной расстановкой акцентов.
Где-то уже писал, что статья не про то. Она про: «ребята, смотрите, go гораздо менее требователен к вашему времени и усилиям по крайней мере на некоторых видах задач. Если ваши задачи схожи, то Go стоит попробовать. Возможно, вы получите некоторый profit.»Randl
30.07.2016 22:17+4Оставьте цифры. Дайте пример с кодом или описанием архитектуры на Java и, соответсвенно на Go.
Без этого создается впечатление именно нубства (может это и не так) из-за 300 клиентов, неспособности запустить профайлер, а также довольно спорного описания самого языка. О проекте при этом ни слова кроме того, что у вас получилось на Go лучше чем на Java.
softaria
31.07.2016 09:01Вы хотите от меня доказательств заведомо ложного тезиса вида «На java нельзя создать такой же быстрй сервер, как на go». Можно. Я думаю, он даже будет поддерживать несколько бОльшее количество клиентов.
Я утверждал лишь, что создание такого сервера на go занимает меньше времени и сил.
Как наличие (плохого) кода на java и хорошего на go может подтвердить или опровергнуть моё утверждение?Randl
31.07.2016 11:05+2Я утверждал лишь, что создание такого сервера на go занимает меньше времени и сил.
Есть разница между "на Go разрабатывать проще и быстрее, чем на Java, благодаря дизайну языка" и "на Go разрабатывать проще и быстрее, чем на Java, потому что я плохо знаю Java". Вы демонстрируете именно второй случай, а он мало кому интересен.
Как наличие (плохого) кода на java и хорошего на go может подтвердить или опровергнуть моё утверждение?
Наличие (хорошего) кода на обоих языках подтвердило бы, что речь именно о языках, а не о ваших способностях.
softaria
31.07.2016 14:08на Go разрабатывать проще и быстрее, чем на Java, потому что я плохо знаю Java
А go не знаю совсем. Это не меняет дело?
Наличие (хорошего) кода на обоих языках подтвердило бы, что речь именно о языках, а не о ваших способностях.
Но у меня нет хорошего кода на ява, который делает то же самое. Он мне не был нужен.Randl
31.07.2016 14:20+2А go не знаю совсем. Это не меняет дело?
Меняет. Превращает посыл статьи в "нубы, перебирайте языки пока вам не повезет состряпать удачную архитектуру на одном из них". Если бы у вас и на Go ничего не вышло, вы пошли бы дальше? И мы читали бы статью «ребята, смотрите, C# гораздо менее требователен к вашему времени и усилиям по крайней мере на некоторых видах задач. Если ваши задачи схожи, то C# стоит попробовать. Возможно, вы получите некоторый profit.»
softaria
31.07.2016 14:30-3Я просто не вижу смысла спорить с вами о своём профессиональном уровне.
По двум причинам. Во-первых, вы уже все для себя решили, а во-вторых меня не интересует профессиональное мнение человека, который родился в тот год, когда я написал свой первый профессиональный код — часть АСУТП для Сургутской ГРЭС.Randl
31.07.2016 14:53Я самого начала пояснил, что говорю не о вашем профессиональном уровне, а о впечатление, которое создает статья. Извиняюсь если вас задел, раз уж вы опытом хвастаться начали.
softaria
31.07.2016 14:59Это я на случай, что кто-то почитает комменты и согласится с вашим посылом про «нубы, перебирайте языки...» только потому, что я ничего не возразил.
solver
31.07.2016 15:33+6О, пошел в ход возраст. Это много говорит о вас.
P.S. Это случайно не та самая ГРЭС где 2 раза крупные аварии были? Совпадение? ))
solver
30.07.2016 22:19+3> Допустим я скажу, что аналогичная задача на яве заняла у меня X дней, а на go — Y (где Y<X), вас это убедит?
Вы вообще не понимаете, что такое «объективность» чтоли?
>ребята, смотрите, go гораздо менее требователен к вашему времени и усилиям по крайней мере на некоторых видах задач.
Менее требователен по сравнению с чем? Как сравнивали, чем мерили и т.д.
Эта фраза и есть «досужие домыслы».
Вы даже поправляя «позиционирование» статьи, лучше не делаете. Даже в этих каментах вы не понимаете, что делаете и продолжаете разжигать холивар на ровном месте.
Suvitruf
30.07.2016 11:07+1Если честно, я долго пытался понять, шутка это или нет (я про статью). У нас многие игровые сервисы на Java в связке с netty. Оно у меня без особых проблем тысячи коннектов держит.
softaria
30.07.2016 11:13+1Видимо я нечетко расставил акценты — очень много одинаковых комментариев.
Шутка не в том, что java будто бы медленнее. Шутка в том, что решение моей задачи занимает у программиста go намного меньше времени.Optik
30.07.2016 11:27+4С учетом того, что большинство по рассказу выявило в вас профана в java, то да, это конечно очень объективно.
ShadowsMind
30.07.2016 11:37+4Откройте для себя Akka (она кстати поверх Netty работает), там создать сервер слушающий TCP/UDP/Web-soket'ы — это дело пары минут. Там вам и прозрачная модель работы с многопоточнотью, и обсолютно никаких блокировок, и поддержка кластера «из коробки» и еще куча плюшек.
Мне лично Go тоже нравится, игрался с ними недельку после рекомендации знакомого, но для себя не нашел не одного плюса относительно тех задач, которые мне приходится реализовывать на Java, темболее последний год с небольшим работаю со Scala — тут даже сравнивать бесмысленно.softaria
30.07.2016 11:50-2Akka, как и Play — реально хорошие вещи.
Но у меня стояла другая задача. Я хотел проверить гипотезу о том, что на go решение этой задачи потребует меньше усилий, чем на java.
Зачем мне это надо? Потому что мне, как владельцу IT компании, важно не пропустить технологическую волну. Не оставить свою команду работать с устаревшими, неэффективными технологиями и не уступить рынок другим, более шустрым игрокам.
За последние 14 лет ни один из новых языков не дал существенного прироста в производительности. Go оказался первым.
solver
30.07.2016 15:33> Akka (она кстати поверх Netty работает)
Чушь полная. По верх Netty работают как раз примеры которые привел автор: VertX и Play.
Что лишь в очередной раз показывает в нем профана в Java мире.
В Akka же по верх Netty работает только кластер. Т.е. обмен данными между нодами.
И то это выпилят постепенно. Т.к. в Akka уже есть своя отличная реализация сокетов, модуль Akka.io.ShadowsMind
30.07.2016 18:17Да, в курсе того, что Netty как депенденси только в remote (а cluster в свою очередь от remote зависит). И про то, что они постепенно от нее избавятся тоже слышал (толи в gitter'е, толи на одной из конференций кто-то упоминал). Просто хотел упомянуть этот факт, надо было сразу уточнить.
Кстати, а разве Play в свою очередь не делает потуги в сторону того, чтобы полностью заменить Netty на Akka? По крайней мере где-то упоминалось, что они планируют, если я не ошибаюсь.vadim_shb
30.07.2016 20:15Команда Play пробуют akka-http. Но так как Akka-http еще experimental, и с производительностью там еще не так все гладко, видимо попоробовав — поймут, стоит ли выпиливать netty.
vintage
30.07.2016 13:30+9Если без чего-то можно обойтись, без этого нужно обойтись.
То есть обеспечение безопасности конкурентного доступа на уровне типов — лишняя возможность, а форматировние на уровне языка — жизненно необходимо?
Код на go на 20-30 процентов короче аналогичного на яве
А обработка ошибок приводит к большому количеству однотипного кода.
Взаимоисключающие параграфы.
Достаточно, чтобы у сущности просто были все нужные методы.
Это называется "структурная типизация".
Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом
Это называется "сопрограмма". Везде реализуется на уровне библиотек.
Канал в go это очередь (буфер) в один конец которого можно писать, а из другого читать.
Это называется "блокирующая очередь". Везде реализуется на уровне библиотек.
можно указать как локальное имя, так и адрес пакета в любой современной системе контроля версий (например, в git)
Bazaar поддерживается? Svn?
В go пошли дальше и сделали поддержку управления зависимостями на уровне самого языка.
Для решения этой проблемы используются внешние инструменты — менеджеры пакетов.
Без такой неполноценной поддержки тоже было не обойтись?
vayho
30.07.2016 13:44+6Я не понимаю удивления автора когда он постоянно указывает на прирост в скорости разработки местным комментаторам, но в статье привел цифры прироста производительности.
Товарищ автор, мы программисты(и немного математики) акцентируем свое внимание в первую очередь на цифрах а не на воде что выше.
Все ваши размышления о инструментарии это просто вода, потому что мы о вас и вашем проекте вообще ничего не знаем:
1. Каков опыт разработки на Java, сколь сложные проекты писали до, использовали ли либы которые нужно было использовать в вашей задаче(Netty, Akka, Quasar)?
2. Приведите пример(а лучше несколько) кода на Java и затем тот же код(или ту же часть логики) на Go(идеально ту часть кода которая тормозила и которую смогли оптимизировать).
3. Какие другие языки рассматривали? Их сейчас много это и Rust, Nim, Elixir, да и NodeJS достаточно производителен, Scala или Kotlin на JVM на которых можно супер короткий и производительный код писать.
А еще есть прикольный http://www.ponylang.org/(не рекламы ради просто для разнообразия).
Обычно при переходе на другой язык рассматривают несколько вариантов, и делают некоторый анализ.
4. Приведите хотя бы цифры для разработки, например сколько дней у вас ушло на написания кода на Java и сколько на переписывание на Go. Это важная информация в контексте вашего постоянного уточнения.softaria
30.07.2016 17:55Как бы вы отнеслись к статье, которая бы начиналась рассказом об авторе его опыте и личных достижениях?
Думаю, большинство комментаторов уместно поинтересовались бы — чего это автор тут пиарится, вместо того, чтобы говорить дело.
Смысл статьи коротко можно выразить так — «Люди, смотрите, есть такие задачи, которые на go получается решать намного быстрее, приятнее и эффективнее, чем на java. Будет свободное время — гляньте сами. Время окупится.»
Проект был всего лишь иллюстрацией. Но если вы, или кто-то другой действительно интересуетесь этим проектом, я отпишу тут подробнее.webkumo
31.07.2016 20:27+1Как можно интересовать тем, чего нет? Вы так и не сформировали чёткой иллюстрации/описания вашего проекта. Поэтому сейчас он не может быть интересен сам по себе. А вот как источник дополнительной информации, которая поможет дать оценку «а стоит ли верить автору» — очень даже.
Пока что никаких доказательств ваших слов никто не увидел. Вопрос доверия — так же решается не в вашу пользу (у вас нет «кредита доверия» — вас никто не знает).softaria
31.07.2016 20:31-1Вы так и не сформировали чёткой иллюстрации/описания вашего проекта.
Потому что статья была не о проекте.
Пока что никаких доказательств ваших слов никто не увидел.
Что бы вы посчитали доказательством моих слов?
у вас нет «кредита доверия» — вас никто не знает
Да, это так. Это было частью эксперимента. Мне нужен был честный фидбэк на статью, а не на статью, которую написал «авторитетный чувак».
Я его получил. Теперь я лучше понимаю как надо и как не надо писать статьи на Хабр.
Полезный опыт.
Idot
30.07.2016 14:12+5Принцип простоты звучит так:
Если без чего-то можно обойтись, без этого нужно обойтись.
Это как? Это как в C++ нет ни Юникода, ни нормальной работы со строками? Или что под этим подразумевается?
OpieOP
30.07.2016 17:45+2«Go можно выучить за 2 вечера» стоит отметить, что это это сильно зависит от предыдущего опыта. У меня как у быдлокодера с основным опытом на node.js подробное изучение языка заняло больше времени, т.к. появляется куча новых понятий.
CodeViking
30.07.2016 17:45-1Очень интересная статья, язык Go определённо стоит как минимум внимания. Благодарю за материал.
Gitkan
30.07.2016 17:45> После работы с профилировщиками эта цифра выросла до 2500.
А как получена эта цифра?softaria
30.07.2016 17:47Путем запуска нагрузочных тестов и измерения используемых ресурсов сервера.
Дополнительно запускался и «нормальный» клиент для субъективной оценки поведения игры под этой нагрузкой.
doom369
30.07.2016 20:01+13Хех. А у меня сервер на java держит 10к клиентов на одном виртуальном ядре за 5$ на DigitalOcean. Давайте все на яву назад переходите :).
antonpv
31.07.2016 09:10Я не понял, а где циферки-графики, как было «плохо» на java и как «хорошо» стало на go? Было 20, стало 2500 — весьма размыто…
У Вас, батенька, что-то с архитектурой не так, а не у java проблемы.
quwy
31.07.2016 14:08-2>На одном сервере можно было запустить не более 300 клиентов.
И после этого они будут говорить, что Java не тормозит.softaria
31.07.2016 14:11Java не тормозит. Тормозил мой неоптимальный код и неверно выбранная серверная библиотека.
Обычно в таких случаях берутся (неудобные) инструменты (VisualVM, например), слабые места изучаются и оптимизируется.
Но в этот раз мне попалась статья об аналогичных инструментах в Go.
Мне показалось, что инструменты настолько превосходят java аналоги, что результат будет достигнут намного быстрее.
Так оно и получилось.
izloy1
31.07.2016 14:11-4«на одном виртуальном ядре за 5$ на DigitalOcean» серверок на java генерит ответ минимально за 85 ?s, на Go та же функциональность — 9 ?s.
Даже «простые» единичные запросы к БД на Go быстрее в 2-3 раза, по сравнению с javasoftaria
31.07.2016 14:12+1Есть масса обратных примеров.
Статья не о скорости языка, а о скрости разработки на языке.
ShadowsMind
31.07.2016 22:07У меня есть совершенно другие цифры: вытаскиваем сущность из 12 полей, маппаем в DTO объект, сериализуем в json: ~15ms. Ах да, там еще jwt токен декодится(HmacSHA512) и мапается из json-строки в объект. Стек: Akka HTTP 2.4.8, Slick 3.1.1, Spray Json 1.3.2. Если пооптимизировать и «прогреть», то будет еще шустрее. (это не Java, а Scala, но какая разница если ранается под JVM).
А Ваши цифры и выводы без информации о том как и на чем было написано не нужны никому… Если уж хотите поевангелировать Go, то делайте это нормально. А то одолели уже эти околохоливаные посты/комменты гоферов и постоянный наброс на вентилятор.ShadowsMind
31.07.2016 22:20-1Забыл упомянуть: БД — PostgreSQL. Обычный JDBC драйвер(есть просто postgresql-async, возможно он быстрее), для пула коннектов — HikariCP. Никаких доп флагов для JVM не выставлял.
firsttimecxx
31.07.2016 16:59+6>>Потом появились треды (или нитки). Они были гораздо легче и работали в одном адресном пространстве. Если процессов обычно запускали единицы или десятки, то тредов можно было иметь уже сотни.
И какое отношение «было» имеет к сейчас и к го?
>>Однако, при неаккуратном использовании и они могли отнять все ресурсы системы.
Не могли. Никогда.
>> Каждый тред всё-таки занимал какие-то ресурсы, даже если был заблокирован.
Не занимал, а занимает. При этом точно так же он занимает в го, при этом это «занимает» ничего не занимает в сравнении с оверхедом ГЦ.
>>Чтобы ограничить число тредов, начали использовать тред пулы.
Не верно. Тредпул, если это именно тредпулл с постоянно живущими потами — существует не для это. Он существует для нивелирования оверхеда на запуск потока.
>>Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом. В Go горутины крайне дешевы.
Го тут непричём — го лишь одна из реализаций юзерпейс «тредов». И при этом «дешевы» — это не верно.
>>Вы можете запустить миллионы горутин без проблем для производительности.
Если под производительностью имеется ввиду как во всех бложиках «спящие треды не отъедают производительность» — это точно так же работает и в системных потоках.
>>Единственное требование — горутины должны быть «маленькие».
Не да, чтобы не надо было шедулить много активных горутин. Типичное проявление слабости шедуллера.
Я уже слышал столько легенд об «тормазящих системных потоках, которых нельзя запустить больше 20», «запустил 100системных потоков и даже спящие съедят 100% цпу» и прочее.
Но проблема как всегда в том, что когда адептам рассказывают что-то про «горутины вс системные треды» — почему адепты никогда не требуют доказательств? Сколько бы я не гуглил — я не увидел ни единого бенчмарка, либо сравнения с системными тредами.
Берём пишем простой бенч — создаём 100500(линукс больше не может, вернее он там и больше 30к активных не может) тредов с телом «инкремент атомика», а после смотрим за сколько все эти 100500 тредов отработали.
package main import "fmt" import "sync/atomic" func main() { var ops uint64 = 0 var n = 100500; for i := 0; i < n; i++ { go func() { atomic.AddUint64(&ops, 1) }() } for atomic.LoadUint64(&ops) < uint64(n) {} fmt.Println(atomic.LoadUint64(&ops)) }
#include <thread> #include <vector> #include <atomic> #include <cstdio> int main() { std::atomic<size_t> c{0}; size_t n = 100500; for(size_t i = 0; i < n; ++i) std::thread{[&](){++c;}}.detach(); while(c < n) {} fprintf(stderr, "%lu\n", (size_t)c); }
pthreads
100500
real 0m0.288s
user 0m0.040s
sys 0m0.250s
Go
100500
real 0m0.226s
user 0m0.340s
sys 0m0.010s
В конечном итоге мы видим, что го еле-еле на 30% быстрее. При этом эту разницу можно выкрутить почти в ноль, если затюнить pthread/ведро.
Ну и так же мы видим, что создание даже 100500 тредов, которые ничего не делаю нихрена не «бесплатно», а даже очень платно.
Если же впилить в С++ слипы в каждый тред, то оно отработает так же(правда надо уменьшить количество до 30к, иначе падает с «кончились ресурсы»). Если же впилить в го — оно встанет раком. Может я просто не так писал слипы в го?
AterCattus
31.07.2016 18:10+1К
Если же впилить в го — оно встанет раком. Может я просто не так писал слипы в го?
package main import "fmt" import "sync/atomic" import "time" import "sync" func main() { var ops uint64 n := 100500 var wg sync.WaitGroup wg.Add(n) for i := 0; i < n; i++ { go func() { atomic.AddUint64(&ops, 1); time.Sleep(1*time.Second); wg.Done() }() } wg.Wait() fmt.Println(atomic.LoadUint64(&ops)) }
Вывод:
100500
real 0m1.289s
user 0m0.978s
sys 0m0.105s
n := 1005000
Вывод
1005000
real 0m3.618s
user 0m9.097s
sys 0m0.671s
n := 1005000
time.Sleep(0*time.Second)
Вывод
1005000
real 0m0.236s
user 0m0.574s
sys 0m0.008s
firsttimecxx
31.07.2016 21:56Т.е. я не могу просто что-то запустить в мейн-потоке? Почему? Какие для этого есть причины?
По поводу вашего кода — вайл там не столько для ожидания завершения, сколько эмуляции нагрузки на основной поток.AterCattus
31.07.2016 22:35Можно. Именно прямо ваш код:
real 0m0.027s
user 0m0.057s
sys 0m0.004s
Именно ваш с миллионом горутин
real 0m0.238s
user 0m0.548s
sys 0m0.012s
С миллионом горутин и паузами (*)
1005000
real 0m2.446s
user 0m5.839s
sys 0m0.714s
// * но для равноправия потоков заменить for atomic.LoadUint64(&ops) < uint64(n) {} // на это var wg sync.WaitGroup wg.Add(1) go func(){ for atomic.LoadUint64(&ops) < uint64(n) {} wg.Done() }() wg.Wait()
firsttimecxx
31.07.2016 22:44Можно.
но для равноправия потоков заменить
Надо определиться. В данном случае код запускается на в мейн-потоке, а в отдельной горутине. У меня мой код не работает и никаких реальных причин из-за которых он может не работает — нет, кроме каких-то слабых мест в реализации го.
Именно ваш с миллионом горутин
Какие-то невероятные результаты. Скорее всего там 100к горутин.
С миллионом горутин и паузами (*)
Ну это уже цифры как у меня. Правда выжирает оно 2.5 ядра, что в 2.5 раза медленее птредов. Ниужели го более той болезнью, в которой обвиняли системные треды, при этом системные треды ею не болеют?
AterCattus
01.08.2016 00:50+1Какие-то невероятные результаты. Скорее всего там 100к горутин.
Да. Ошибся. С миллионом выходят ~2.5сек.
Надо определиться.
Первые два примера только ваш код (во втором случае разве что n увеличено в 10 раз). Никаких больше правок.
Изменение коснулось только последнего примера со слипами.
Правда выжирает оно 2.5 ядра, что в 2.5 раза медленее птредов
pthreads
real 0m0.288s
sys 0m0.250s
Go
real 0m0.226s
user 0m0.340s
У вас C++ сидел в ядре (обрабатывая 100500 потоков), а Go в юзерспейсе (100500 горутин на 4-8(?) потоков). При этом Go съел чуть больше проца, но и завершился чуть быстрее.
Кстати, вот про шедулинг горутин (хоть и не самый свежий), реализацию стека и прочую начинку:
https://habrahabr.ru/company/ua-hosting/blog/269271/
https://habrahabr.ru/company/mailru/blog/283038/
https://habrahabr.ru/post/276255/
https://habrahabr.ru/company/intel/blog/275709/firsttimecxx
01.08.2016 01:40+1Первые два примера только ваш код (во втором случае разве что n увеличено в 10 раз). Никаких больше правок.
У меня не работает мой код — он просто зависает и всё. Хотя причина вроде понятна — оно не завершается пока все горутины не завершены, даже если я их не жду, что странно.
У вас C++ сидел в ядре (обрабатывая 100500 потоков)
Ну он не только в ядре сидел. Он сидел 100500 раз в ядре и 100500 раз в юзерпейсе.
При этом Go съел чуть больше проца, но и завершился чуть быстрее.
Ну если в этих горутинах будет не инкремент атомина, который на фоне всего стоит в районе нуля, а что-то посерьёзней, то быстрее они уже не завершатся.AterCattus
01.08.2016 15:22>оно не завершается пока все горутины не завершены, даже если я их не жду, что странно.
Какие-то горутины не могут получить управление, чтобы отработать, потому цикл ожидания никогда и не завершается.
Добавьте runtime.Gosched(), как вам уже советовали.
> а что-то посерьёзней, то быстрее они уже не завершатся
Как бы разница в пользу Go не стала выше из-за отсутствия переключений ядра и юзерспейса.firsttimecxx
01.08.2016 19:29+3Какие-то горутины не могут получить управление, чтобы отработать, потому цикл ожидания никогда и не завершается.
Ещё раз. Меня не интересует как сделать так, чтобы это работало. Меня интересует то — по какой причине это не работает так, как написал я.
Добавьте runtime.Gosched(), как вам уже советовали.
Это не ответ. Вопрос был не в этом. Повторю в третий раз — почему оно не работает так, как написал я. Какие предпосылки к этому есть, кроме дыры в дизайне.
Как бы разница в пользу Go не стала выше из-за отсутствия переключений ядра и юзерспейса.
Опять же ни на чём не обоснованные утверждения. На основании чего там станет переключений больше? Потому что кто-то сказал?
Ну и для справки — переключение ничего не стоит. Особенно на фоне всплывших подробностей работы горутин с сисколами. Как будет время — я напишу бенчмарки с сисколами и добью эту тему. Другой оратор уже поплыл — до подробностей кричал «горутины аналог мультиплексинга», а после уже «надо юзать горутины с епулом, который собственно их аналогом и является. Бывает.
Falstaff
01.08.2016 19:47Другой оратор уже поплыл — до подробностей кричал «горутины аналог мультиплексинга», а после уже «надо юзать горутины с епулом, который собственно их аналогом и является.
Не «надо юзать», а «библиотека Go под капотом юзает». Это и есть мультиплексинг. А вообще, firsttimecxx, завязывайте с таким тоном. Вам тут никто ничего не обязан, в том числе по десять раз объяснять всё, что все остальные давно уже поняли или с самого начала знали. Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop? Не знаете, как работают async/await? Бывает. Жизнь — процесс познания нового. Только хамить не надо.
firsttimecxx
01.08.2016 21:28+2Не «надо юзать», а «библиотека Go под капотом юзает». Это и есть мультиплексинг.
Это не ответ. Ещё раз, меня никаким тоном пугать не надо. Меня это мало волнует.
Хорошо, раскатывать — так раскатывать.
Утверждение раз:
Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей.
Суть — противопоставление мультиплексинга(libevent) и горутин.
Утверждение два:
Там, где в го используются горутины, в C вы обычно используете libevent а не потоки.
Противопоставление горутин и мультиплексинга — два.
Далее, когда оратор был зажат в угол — последовало:
Но вы можете сделать иначе — вы можете использовать событийную модель. Горутина может вызвать собственную сетевую библиотеку, а та, обёртывая системные вызовы, добавляет сокет в список ожидания epoll(). При этом заблокируется только один поток на все сокеты.
Опустим событийную модель — она тут не при делах и я не буду это разоблать, что epoll не про событийную модель, но это такое.
Чтобы оратор опять не поплыл с моделью использования горутин — уточним:
Миллион одновременных клиентских соединений? Это чуть ли не канонический use case. Живут, что-то считают, засыпают на ввод-вывод, снова просыпаются, умирают.
Суть — поток данных клиент/сервер находится в своём потоке(выполнения). Это юзкейс для горутин, что собственно выше я и писал.
Далее, мультиплексинг — это про сбор множества потоков данных в один поток, который обрабатывает уже один поток(выполнения) и нет смысла использовать для этого множество потоков(выполнения).
Что мы имеем. Оратор, утверждая изначально о назначении горутин как об альтернативе мультиплексинга, т.е. не много потоков(данных) в один поток данных в один поток обработки, а в множество поток данных в множество потоков(исполнения) вдруг переобулся и начал утверждать обратное. Типичное натягивание совы на глобус и подбивание всего под себя.
Далее пошла типичная тактика обвинять меня в том, что я чего-то не понимаю и он видите ли мне что-то объясняет, а я не понимаю.
Такую же тактику использует адепт ниже, только он на вопрос «почему не работает?» — отвечает «вставьте кастыль — заработает», и каждый раз утверждает, что он отвечает.
Всё это сводится к тому, что адепты за меня придумывают то, что спрашивал я, игнорирую мои вопросы и подменяя их тем, что выгодно им, а далее уже обвиняют меня в том, что придумали они.
Жизнь — процесс познания нового. Только хамить не надо.
Просто смешно. Может мне спросить основание для обвинения меня в " Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop?"? И будет очередное «поплыл»?
Ну и конечно же хамить. Это любимое занятие слабой аудитории — сливаться на «хамить» и прочее. А на вопрос «где я хамил» — обвинитель ничего показать не может, а если и может, то связать цитату и «хамил» логически не может.
Это я ещё не начал разоблачать " с самого начала знали." и сливы вида «итак было ясно, что системные потоки не медленнее». Это делается очень просто — я ищу на хабре все статьи про го, в которых упоминается «быстрее» написанные после вышей регистрации и если там не будет в ответах опровержения от вас, либо найду у вас цитатку подобную.Falstaff
01.08.2016 21:39-2«Тактика», «адепт», «раскатывать»… в странном мире вы живёте. Извините, но еда — всё. Спасибо за диалог.
firsttimecxx
01.08.2016 22:09+2«Тактика», «адепт», «раскатывать»… в странном мире вы живёте.
Я живу в этом мире. Не я сливаюсь, не я веду себя так. Не моя тактика основа на вранье, обвинения, уличениях и прочем непотребстве.
Люблю эту адиторию. Много из себя строит, а после первых трудностей сбегает.
Меня все удивляли эти интерпретации и ЧСВ. Когда кто-то что-то спрашивает типчный адепт начинает строить из себя учителя, предполагая, что тот, кто спрашивает чего-то не знает. А раз не знает — ему можно впаривать любою херню, но суть в вере в себя. Адепт начинает думать, что он выше того, кто спрашивает.
Но иногда бывает так, что тот кто спрашивает — спрашивает это не для того, чтобы ему объяснили. А для того, чтобы адепт на кураже выложил все свои представления о теме. А далее эти представления очень просто разбиваются.
Ну и да, играть в игру «я не говорил, я не я» с более сильным не имеет смысла, ибо в любом случае разоблачат. Такие дела.
AterCattus
01.08.2016 19:51+2по какой причине это не работает так, как написал я.
почему оно не работает так, как написал я
Если вы на 4х ядрах без вытесняющей многозадачности запустите 4 cpu-bound потока, а потом захотите запустить 5ый, но он не будет выполняться, — это тоже дыра в дизайне? Больше похоже на неправильное использование.
Вы ставите задачи шедулеру, но не даете ему работать. Вам это уже писали.
На основании чего там станет переключений больше
Потому что нет постоянных переключений огромной кучи потоков. Каждый поток (а их мало, единицы) имеет свою очередь горутин на выполнение, и просто их выполняет по очереди, не покидая юзерспейс.
P.S. Если так хочется посравнивать, можете сделать просто два распараллеленных cpu-bound теста рассчетов на хотя бы 10к горутин и 10к потоков. Какой быстрее посчитает и сколько ресурсов съест. Всякие -O2 и -O3 оптимизации для кода на плюсах использовать будет не спортивно, для схожести машинного кода.
firsttimecxx
01.08.2016 21:55+3Ну это просто смешно. Неужели вы реально думаете, что такая попытка чего-то стоит?
Если вы на 4х ядрах
Во-первых враньё номер раз. Ни на каких ядрах и ничего я не запускал. Я в мейн-потоке запустил 100500горутин, а далее в мейнпотоке был цикл, который никак не мог заблокировать остальные потоки.
без вытесняющей многозадачности
Приплыли. Ведь отсутствие вытесняющей многозадачности это и есть дыра в дизайне любых гринтредов.
запустите 4 cpu-bound потока
Очередной враньё. Никакие потоки запущены не были. Никакие cpu-bound-задачи на них не запускались. Запускался слип.
Слип никак не может заблокировать поток, ибо он уже своей логикой вытесняет поток. Иная логика — дыра в дизайне.
а потом захотите запустить 5ый, но он не будет выполняться, — это тоже дыра в дизайне?
Опять враньё. В го потоки(реальные потоки) вытесняемые. Иначе быть не может. Если же это не так — никаких 4-х процессоров нет и вся попытка изначально подлог, а однопоточный дизайн — дыра в дизайне.
Больше похоже на неправильное использование.
Ещё раз. Никаких вменяемых оснований для называния моего кода неправильным нет. Блокировка мейн-потока никак не может влиять на другие потоки, либо запущенные горутины, либо из шедулер. По определению.
Тем более всё это изначальный подлог, ибо создание горутины находится выше и шедулер 100% запустился.
Единственная причина такого поведения — это нахождения шедулера и прочего управляющего кода в мейн-потоке, что является дырой в дизайне по определению.
P.S. Если так хочется посравнивать, можете сделать просто два распараллеленных cpu-bound теста рассчетов на хотя бы 10к горутин и 10к потоков.
Перед тем как предлагать что-то — надо выкатывать основание, либо вменяемые предположения следствием из которых будет являться осмысленность данных предложений. С чего вдруг горутины выиграют?
Какой быстрее посчитает и сколько ресурсов съест. Всякие -O2 и -O3 оптимизации для кода на плюсах использовать будет не спортивно, для схожести машинного кода.
Предложение является дырявым и не имеющим смысла. Когда я что-то измеряю я измеряю только то, что нужно. Поэтому я не буду писать так, чтобы слабость компилятора и рантайма го проявлялась.
По поводу вашего предложения — написать на го лучше вам, ибо я этот язык вижу в первый раз.
Делается же это не так. Берётся 100% масштабируемая задача время выполнения 10к запусков которой поделенное на n реальных ядер(либо лучше посчитать сразу в n-топоках по 10к/n запусков)учитывается как эталон. Далее всё это запускается на 10к тредах и высчитывается оверхед.
По поводу го. Если с сями/крестами я уверен в том, что эталонное время будет состоять на >99% из времени исполнения того куска кода, что написал я. То в го это может быть не так. Он может 50% времени долбить свой шедуллер/рантайм, либо ещё какую херню и результирующих цифрах мы полечим 50% мусора. Но это ладно.
Всякие -O2 и -O3 оптимизации
Кресты без оптимизаций не имеют смысла к существованию. При этом надо понимать, что -O0 — это не отсутствие оптимизаций, а наличии пессимизаций из-за волатайла.
Но это ладно — я сделаю честно.iqiaqqivik
02.08.2016 07:41+3Вообще про «не включать `-ON` — самый смешной пассаж. Почему вдруг при соревновании в беге двух сущностей я должен своей отрубить ногу?
firsttimecxx
02.08.2016 08:11Не, ну это имеет смысл. Автор пытается исключить возможный выигрыш С++ за счёт более оптимальной реализации задачи, которая собственно и будет запускаться на 10к тредах. И в конечном итоге получится так, что С++ быстрее/такой же, но на самом деле его полезная нагрузка просто жрёт в n-раз меньше цпу, что собственно и нивелирует больший оверхед самих потоков в сравнении с горутинами.
Для того, чтобы это избежать — надо сравнивать реализации не друг с другом, а с деградацией в сравнении с запуском 10к раз на одном(ncpu) тредах.
Falstaff
31.07.2016 18:12Может я просто не так писал слипы в го?
Скорее всего вы попались на такой нюанс: если вы добавите в ваши процедуры Sleep(), но после их запуска будете непрерывно, в цикле, проверять атомарную переменную (как у вас в примере), то этот цикл просто не отдаст управление гопроцедурам. Не забудьте, что ими управляет не планировщик ОС, а потому надо дать возможность этому планировщику запуститься — главный поток должен заблокироваться хоть ненадолго. В вашем примере проще всего вставить очень маленький Sleep() в цикл проверки переменной.
Вообще, вы по сути проверили скорость создания потоков. Создание потоков в Linux это быстрая штука, спору нет. Но вы же сами написали, что при равном количестве потоков/процедур у вас пример на C++ вылетает с нехваткой ресурсов. Потоки куда тяжеловеснее по стеку (по умолчанию, если память не изменяет, там два мегабайта), у горутин — два килобайта. Вставьте задержку и посмотрите на maximum resident size, я думаю, что код на C++ покажет гораздо больший расход памяти.
firsttimecxx
31.07.2016 21:33+1то этот цикл просто не отдаст управление гопроцедурам.
Ну дак цикл там один, а вёдер у меня 8. И судя по тому, что я нагуглил — го не однопоточный, а может раскидывать всё это на несколько тредов, либо этого он не может?
Не забудьте, что ими управляет не планировщик ОС, а потому надо дать возможность этому планировщику запуститься — главный поток должен заблокироваться хоть ненадолго.
А что ему мешается запустить в параллельном треде? Тем более он запустился — он же вызвал горутину в которой есть слип. В чём проблема?
В вашем примере проще всего вставить очень маленький Sleep() в цикл проверки переменной.
Этот цикл — эмуляция нагруженного реального потока. Собственно это ещё одно причина из-за которой «горутины должны быть маленькие», хотя ничего не мешает расставлять какие-нибудь стоп-поинты(аля pthread_testcancel()).
Вообще, вы по сути проверили скорость создания потоков.
Ну да, ведь горутины именно про это.
Создание потоков в Linux это быстрая штука, спору нет.
Судя по бложикам го, судя по хайпу вокруг горутин — все меня(и не только меня) убеждают в том, что ОС не может даже в 100тредов.
Но вы же сами написали, что при равном количестве потоков/процедур у вас пример на C++ вылетает с нехваткой ресурсов.
Нет. Я писал не так — я писал, что активных потоков может быть 30к из-за каких-то ограничений линукса. А так же я написал, что я не знаю таких юзкейсов где надо иметь больше 30к АКТИВНЫХ потока.
Потоки куда тяжеловеснее по стеку (по умолчанию, если память не изменяет, там два мегабайта)
Сколько там мегабайт в стеке не имеет значение — занимать всегда будет столько, сколько используется кратно 4килобайтам.
Это тратит только адресспейс, которого:
address sizes: 39 bits physical, 48 bits virtual
И уж даже если взять под потоки 41бит — это в миллион раз больше, чем 2мегабайта.
Поменять же размер стека никаких проблем не состовляет:
pthread_attr_t attr_d, * attr = & attr_d; pthread_attr_init(attr); pthread_getattr_default_np(attr); pthread_attr_setstacksize(attr, PTHREAD_STACK_MIN); pthread_setattr_default_np(attr); pthread_attr_destroy(attr);
у горутин — два килобайта.
Ну обычно у стека есть защита — последняя страница ставить с prot_none и при при заходе на неё падает с «сегфолтом».
Если у го её нет, то значит любая горутина может спокойно покараптить стек другой горутины, а если она есть — стек уже не 2кб, а 8кб минимум.
>>Вставьте задержку и посмотрите на maximum resident size, я думаю, что код на C++ покажет гораздо больший расход памяти.
Не покажет. Я уже объяснил причины. По поводу памяти — при любом стеке птреды будут занимать 8кб на один тред(страница активный + страница для защиты). Если в го — это 2кб, то будет занимать в 4раза меньше.
Опять же — ничего не мешает запилить аналог птреда и с 2кб стека, правда всех мало волнуют эти 100мегабайт на 100к тредов.
И опять же, как я говорил — гц в реальном приложении на го сожрёт куда больше.AterCattus
31.07.2016 22:23любая горутина может спокойно покараптить стек другой горутины
Через unsafe можно, еслипочтиспециально. На то он и unsafe. В обычной жизни нет (не рассматриваем ситуацию сейчас с багом самого го рантайма).firsttimecxx
31.07.2016 22:37Как это реализуется? Это только подсчёт длинны стека, но опять же — это значит, что не вызовешь никакой сишный код. При этом это оверхд не слабый. Это можно реализовать как-то ещё?
Falstaff
31.07.2016 23:05Реализуется проверкой в прологах функций (оверхед там небольшой). Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется. Здесь оверхед, да, ощутимый, но иначе никак. (Простите, что не с свой разговор влез.)
firsttimecxx
01.08.2016 02:25+1Реализуется проверкой в прологах функций (оверхед там небольшой).
Ну хотя да, если там нету vla и прочих историй, то длину стека функции может почитать компилятор.
Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется.
Но ведь суть всей ассинхронки именно во внешних операциях. Прочитать сеть, записать на диск, вызвать бдешку и прочее, а всё это си. Каким образом это работает?
(Простите, что не с свой разговор влез.)
Это общий разговор.
Falstaff
01.08.2016 02:38Каким образом это работает?
Мы говорим о вызове функций из нативных библиотек, или уже об асинхронном вводе/выводе? Если горутина делает блокирующий системный вызов, то поток, в контексте которого она выполняется, будет заблокирован этим вызовом, а остальные горутины уйдут в очереди других потоков.
firsttimecxx
01.08.2016 02:50Мы говорим о вызове функций из нативных библиотек, или уже об асинхронном вводе/выводе?
Любая связь горутины с реальным миром — это код нативных библиотек. Единственная причина по которой это может быть не так — реализация на го обёрток вокруг сисколов, да и в целом переписывания всего либц на го.
Если горутина делает блокирующий системный вызов
Я говорю про это:
Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется.
Хотя на блокирующих вызовах это крах всей логики горутин, ибо оно будет плодить потоки системные + смена стека, а на вызовах не блокирующих.
Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные, либо внешние, но опять же — через всё это системное ipc, либо сеть, либо файлы.
Falstaff
01.08.2016 03:39Единственная причина по которой это может быть не так — реализация на го обёрток вокруг сисколов, да и в целом переписывания всего либц на го.
В Go очень много обёрток и собственных реализаций, в том числе для того, чтобы отвязать горутины от блокирующих системных вызовов. И отсюда же очень малое количество зависимостей у бинарников.
Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные...
Я опять обращусь к примеру. (Сразу скажу, конкретной реализации именно этой части в Go не знаю, так что пример умозрительный, но кажется, что так и реализовано.) У вас есть несколько горутин, ожидающих ввода/вывода на сокетах. Вы можете сделать несколько потоков и каждый будет ждать ввода вывода, каждый будет иметь горутину в контексте исполнения. Но вы можете сделать иначе — вы можете использовать событийную модель. Горутина может вызвать собственную сетевую библиотеку, а та, обёртывая системные вызовы, добавляет сокет в список ожидания epoll(). При этом заблокируется только один поток на все сокеты. Как только epoll() просигналит, что на каком-то сокете доступен результат ввода-вывода, то это событие поступит в очередь событий, а планировщик даст зелёный свет на выполнение той горутине, которая ждала этой операции. Ради таких вещей горутины и задумывались.
AterCattus
01.08.2016 13:48Ну так Go и не использует libc (или что там идет заменой на других платформах, типа той же винды). Прямые сисколы, а вызов именно сишного кода только для явного вызова сишного кода, а не i/o и прочего.
Falstaff
31.07.2016 22:54+1… может раскидывать всё это на несколько тредов, либо этого он не может?
Горутины, конечно, разбрасывает. Но вы не дали планировщику их разбросать. Дело не в том, чтобы запустить горутину, которая спит, дело в том, чтобы выбрать сигнал на её пробуждение в цикле событий, который там под капотом.
Этот цикл — эмуляция нагруженного реального потока.
Горутины — не потоки.
Ну да, ведь горутины именно про это.
Нет, они не про это.
… все меня(и не только меня) убеждают в том, что ОС не может даже в 100тредов.
Ну, как видите, 100500 потоков не может, а 100500 (и гораздо больше) горутин может. Но это сравнение тёплого с мягким, это довольно разные вещи. Это распространённое заблуждение, думать о горутинах как о потоках.
… горутина может спокойно покараптить стек другой горутины, а если она есть — стек уже не 2кб, а 8кб минимум.
Го вставляет проверки доступного размера стека в прологи генерируемых функций, если стека не хватает на нужды функции, то он растёт. Поэтому guard page нет, и это вполне безопасно.
Не покажет.
Если в го — это 2кб, то будет занимать в 4раза меньше.
Ну вот видите, покажет. Тоже вполне себе разница. В реальности будет больше (я не поленился — шесть раз). Плюс маленькие приятности вроде переключения контекста из юзерспейса и обратно.
Но и это действительно не так уж важно, никого и впрямь не волнует расход памяти на потоки при таком чудовищном их количестве — просто потому что в таком количестве их никто не использует. Почему важно то, что горутины весят меньше, и почему их, бывает, запускают в таких количествах? Потому что горутины — это не потоки. Они используются не для распараллеливания вычислений и тому подобного. (Нет, используются, конечно, они всё-таки бегут поверх пула потоков, но это второстепенно.) Настоящая raison d'etre горутин и каналов в го — это асинхронное выполнение. Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей. Поэтому споры «горутины vs. системные треды» — довольно бесполезное времяпрепровождение. :)
firsttimecxx
01.08.2016 02:19-2Горутины, конечно, разбрасывает. Но вы не дали планировщику их разбросать. Дело не в том, чтобы запустить горутину, которая спит, дело в том, чтобы выбрать сигнал на её пробуждение в цикле событий, который там под капотом.
Не понят причём тут горутина, причём тут цикл событий? Ничего ему не мешает «их разбросать».
Горутины — не потоки.
Горутины тут не причём. Я вызвал цикл в основном потоке и всё втало раком. Потоки ли горутины, либо нет — никому не интересно и это ничего не меняет.
Нет, они не про это.
Именно про это. Если не про это — я слушаю ваши предположения.
Ну, как видите, 100500 потоков не может, а 100500 (и гораздо больше) горутин может.
Это не имеет смысла. Оно может во столько, сколько использовать имеет смысл. Работает не медленнее, при этом имеет преимущества системных потоков.
Может 100500 активных потоков, но 100500 активных потоков в го быть не может — может быть только(один? 4? 8?). 100500 потоков в слипе никому не нужно, ибо во-первых они будятся через адские кастыли, а во-вторых — стоимость их пробуждения будет нивелировать их смысл.
При этом, если считать честно — горутины создаются и управляются медленнее системных потоков, ибо потребляют больше процессорного времени в сравнении с системными.
Если не подменять понятия, то реальный юзкейс — это именно создание потоков, которые отрабатывают и уничтожаются сразу, а не живут миллионами одновременно(это не имеет смысла из-за оверхеда на пробуждение). В этом юзкейсе системные потоки не уступают горутинам, которые должны быть быстрее.
>>Го вставляет проверки доступного размера стека в прологи генерируемых функций, если стека не хватает на нужды функции, то он растёт. Поэтому guard page нет, и это вполне безопасно.
Это дороже. Опять же — как вызывать нативные(сишные) функции?
>>Ну вот видите, покажет. Тоже вполне себе разница.
Разница в чистых цифрах никакая тем более в сравнении с го в котором есть гц.
>>В реальности будет больше
Не будет. Будет именно так, как посчитал я. Не согласны — предъявите основание вашего утверждения.
я не поленился — шесть раз
Я померил — го 70мегабайт, а птреды 260. Запускалось это на 30к тредах, ибо линукс в больше не может. Как я сказал — тред 8кило * 30к, что ~235 мегабайт, что соответствует реальности. 30к * 2к — это ~59мегабайт, что соответствует наблюдаемым.
Почему важно то, что горутины весят меньше
Как мы уже выяснили — их «меньше» не преимущество, ибо в чистых цифрах оно ничтожно.
, и почему их, бывает, запускают в таких количествах?
Зачем?
>>Потому что горутины — это не потоки.
Это потоки. Им можно какие угодно вешать шильдики, но это потоки.
Они используются не для распараллеливания вычислений и тому подобного.
Поток не про распараллеливание — поток про «поток» — т.е. про параллельное исполнение множества потоков управления.
(Нет, используются, конечно, они всё-таки бегут поверх пула потоков, но это второстепенно.)
Как и обычные потоки.
Настоящая raison d'etre горутин и каналов в го — это асинхронное выполнение.
Насколько я знаю — это именно треды.
Т.е. если я создам цепочку горутина->канал->горутина и т.д. — это будет не один поток, а 2.
Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей.
Всё это логика над потоком управления, вернее разделение одного на множество и сборка обратно. Треды — это про запуск этих потоков, а каким образом происходит этот запуска — это отдельная история.
Запускать это в горутинах, либо в потоках — разницы нет. Вернее как го-пацаны говорят, что есть, ибо горутины быстрее потоки, но это не совсем так, вернее совсем не так.
Поэтому споры «горутины vs. системные треды» — довольно бесполезное времяпрепровождение. :)
Да нет, это просто отмазки для избежания неудобной ситуации перед простым фактом — горутины не быстрее.
То, что в го есть какая-то логика поверх потоков — из этого ничего не следует. Прикрутить её можно куда угодно.
Были бы это не потоки, если бы все эти цепочки горутина->канал->горутина объединялись бы в цепочку калбеков в рамках одного потока.Falstaff
01.08.2016 03:22+5… причём тут цикл событий? Ничего ему не мешает «их разбросать».
Я думаю, что тут будет удобнее на примере. В вашем коде, сразу после создания потоков, но до начала цикла поллинга вашего атомика (не внутри цикла, а до него), поместите один вызов runtime.Gosched() — сделайте одно переключение в контекст планировщика. После этого цикл может работать без пауз, но горутины уже завершатся нормально.
Именно про это. Если не про это — я слушаю ваши предположения.
Мне кажется, я уже рассказал, про что. Горутины — не для того же, для чего используются потоки. Там, где в го используются горутины, в C вы обычно используете libevent а не потоки. Да, их можно использовать для распараллеливания работы (если GOMAXPROCS не единица), но концептуально это инструмент для написания асинхронного кода.
Это не имеет смысла. Оно может во столько, сколько использовать имеет смысл.
Хорошо. Сделайте на вашей машине миллион. Не теоретически, а экспериментально.
Может 100500 активных потоков, но 100500 активных потоков в го быть не может — может быть только(один? 4? 8?). 100500 потоков в слипе никому не нужно...
А зачем вам активных 100500? У вас есть восемь ядер, поэтому всё, что вы создаёте сверху — явно не для того, чтобы держать их всех активными. Здесь мы возвращаемся к тому, что уже обсуждали — если вы создали 100500 потоков или горутин, то это не ради распараллеливания работы, это для асинхронной модели выполнения. Для этого и сделаны горутины.
Если не подменять понятия, то реальный юзкейс — это именно создание потоков, которые отрабатывают и уничтожаются сразу, а не живут миллионами одновременно...
Миллион одновременных клиентских соединений? Это чуть ли не канонический use case. Живут, что-то считают, засыпают на ввод-вывод, снова просыпаются, умирают.
Это дороже. Опять же — как вызывать нативные(сишные) функции?
Не сильно дороже. Впрочем, об этом выше был разговор — нативные вызываются со стеком потока, в контексте которого выполняется горутина. Да, там оверхед — надо копировать данные со стека на стек и обратно.
Не согласны — предъявите основание вашего утверждения. <...> Я померил — го 70мегабайт, а птреды 260.
Двадцать восемь против ста шестидесяти семи на десяти тысячах. Можете мне рассказать, почему, если не лень. Но это не принципиально.
Зачем?
Для асинхронного выполнения кода.
Это потоки. Им можно какие угодно вешать шильдики, но это потоки.
Нет.
Поток не про распараллеливание — поток про «поток» — т.е. про параллельное исполнение множества потоков управления.
Поток не про распараллеливание, а про параллельное выполнение потоков? Это тавталогия какая-то, извините. В чём различие?
Насколько я знаю — это именно треды. Т.е. если я создам цепочку горутина->канал->горутина и т.д. — это будет не один поток, а 2.
Нет. Если вы установите GOMAXPROCS=1, то вы вполне себе получите один-единственный поток, но горутин будет две. При этом они будут крутиться в очереди выполнения в контексте этого потока. Это крупное различие.
Всё это логика над потоком управления, вернее разделение одного на множество и сборка обратно.
Нет. Async/await и иже с ними не обязательно вызывают создание новых потоков. Фактически под капотом событийная модель — мы можем отметить, что этот кусок кода ожидает события, и как только в очереди событий оно появится, то этому куску даётся зелёный свет на выполнение; это вполне может выполняться в контексте одного потока.
Были бы это не потоки, если бы все эти цепочки горутина->канал->горутина объединялись бы в цепочку калбеков в рамках одного потока.
В чём-то так и есть — это похоже на цикл событий и этакий сахар над колбеками. Для этого не нужны потоки.
Вы как-то всё агрессивнее и агрессивнее становитесь. Я создал у вас впечатление пытающегося сказать, что ваш C++ — убожестно, и Go forever? Это ошибочное впечатление. Я просто пытаюсь объяснить, как всё это работает. Если я вас раздражаю, вы скажите, и я перестану.
SirEdvin
02.08.2016 13:11-3В целом вся концепция "легких" потоков о том, что бы запускать кучу псевднопотоков в одном реальном.
iqiaqqivik
02.08.2016 17:27+1Вот только сегодня как раз вышла прекрасная заметка Адама Левенталя; положу тут, за компанию: http://dtrace.org/blogs/ahl/2016/08/02/i-love-go-i-hate-go/
LK4D4
Никогда не писал на яве, но расписано душевно. Спасибо!
Да, жаль что непроверенная ошибка это не ошибка компиляции. А способ обработки мне кажется это на любителя, многим наоборот нравится после исключений.
ingrysty
В поняшке на стадии компиляции :)
sleeply4cat
Вау, кто-то использует на практике? Какие впечатления?
ingrysty
До практики еще потребуется время, поэтому пока для изучения.
Aleksi
https://github.com/kisielk/errcheck
softaria
Очень интересный инструмент. Вы его пробовали? Как впечатление?
Aleksi
Успользую уже очень давно. Работает.
softaria
Спасибо. Буду пробовать.