Эта статья не для тех, кто уже пишет на go.
Она для программистов на других языках, которым инетересно, стоит ли тратить время на 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)


  1. LK4D4
    29.07.2016 23:19
    +1

    Никогда не писал на яве, но расписано душевно. Спасибо!

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

    Да, жаль что непроверенная ошибка это не ошибка компиляции. А способ обработки мне кажется это на любителя, многим наоборот нравится после исключений.


    1. ingrysty
      30.07.2016 04:20
      +2

      В поняшке на стадии компиляции :)


      1. sleeply4cat
        30.07.2016 22:15
        +1

        Вау, кто-то использует на практике? Какие впечатления?


        1. ingrysty
          31.07.2016 07:30

          До практики еще потребуется время, поэтому пока для изучения.


    1. Aleksi
      30.07.2016 12:36
      +2

      Да, жаль что непроверенная ошибка это не ошибка компиляции.

      https://github.com/kisielk/errcheck


      1. softaria
        30.07.2016 12:38

        Очень интересный инструмент. Вы его пробовали? Как впечатление?


        1. Aleksi
          30.07.2016 12:39

          Успользую уже очень давно. Работает.


          1. softaria
            30.07.2016 12:40

            Спасибо. Буду пробовать.


  1. 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/


    1. softaria
      29.07.2016 23:41
      -2

      Спасибо. Не знал про Java Mission Control. Обязательно попробую.
      Что касается quasar, я сравнивал сами языки, а не экосистему.


      1. AlexTheLost
        30.07.2016 08:34
        +27

        Без обид, но факт что вы не знаете про инструменты анализа производительности JVM, и как видно не удосужились поискать о них информацию говорит не в пользу вашего профессионализма. Но вы все же беретесь сравнивать платформы, а ведь ваш пост будут читать и за счёт авторетета хабра будут рассматривать ваше мнение так же как авторитетное.
        По мимо этого. Я вижу что написание кода на go в лоб, без профилирования не дало высоких показателей(50 человек онлайн) и только после устранения узких мест был рост до 2500. Возможно на java результат будет не хуже?
        Вы говорите об эффективном параллельной обработке данных на go за счёт мощных встроенных средств. Но JVM в своём арсенале уже содержит множество библиотек и Фреймворков, таких как приведено выше и даже более распространённых и проверенных, как Akka. Акторная модель скорее всего решит ваши проблемы многопоточности, не заставляя радикально менять платформу, а такой сервер как netty или модуль akkaHttp проблемы с масштабированием кол-ва соединений.


        1. 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 для этого потребуется намного меньше времени.


          1. Optik
            30.07.2016 09:31
            +23

            Ваши пункты намекают, что ваши знания java возможно даже хуже чем знания go.


          1. Suvitruf
            30.07.2016 10:53
            +12

            Выглядит как «я не хочу разбираться и выбирать необходимый инструмент для Java проекта, поэтому возьму мейнстримный Go».


            1. softaria
              30.07.2016 11:31
              -11

              Я хотел сравнить трудозатраты на решение одной и той же задачи в java и в go.
              В go они существенно меньше для этой задачи.


            1. Source
              30.07.2016 11:44
              +9

              Когда в Go дело доходит до использования сторонних библиотек, то ситуация становится гораздо печальнее, чем в Java. Куча библиотек, которые делают примерно одно и то же, приходится реально вчитываться в код каждой, чтобы сделать адекватный выбор.
              Да что там библиотеки… Попробуйте для начала веб-фреймфорк выбрать: awesome-go#web-frameworks


              1. FireGM
                30.07.2016 19:04
                -4

                Iris же. Можно делать очень быстрые микросервисы, но можно и подобие монструозного django.


                1. iqiaqqivik
                  31.07.2016 18:42
                  +1

                  Фраза «эта прекрасная машина умеет варить суп, жарить мясо и печь пироги» в 102% случаев означает, что все вышеперечисленное эта машина делает отвратительно.


                  1. Suvitruf
                    01.08.2016 09:23
                    -1

                    <sarcasm>Если только под машиной не подразумевается жена</sarcasm>.


          1. valery1707
            01.08.2016 12:48
            +5

            Что взять? Jetty, Netty, а может VertX или Play?

            Как можно всё это свалить в одну кучу и при этом делать вид что разбираетесь в Java?


            • Jetty — эффективный контейнер сервлетов. Да у него довольно эффективный IO, но его основное назначение это именно контейнер сервлетов
            • Netty — фреймворк для эффективного сетевого IO.
            • VertX — фреймворк для написания эффективных сетевых приложений. Собственно для эффективного IO использует Netty
            • Play — полноценный веб-фреймворк, которому для работы нужен контейнер сервлетов

            Да даже просто причитать описание проектов на вики хватило бы что бы выбрать нужный.


    1. grossws
      30.07.2016 02:44
      +3

      Стоит добавить, что для использования JMC и Flight Recorder на приложении в production'е необходимо иметь специальную лицензию от Oracle (Java SE Advanced/Java SE Suite), как и для остальных Commercial Features. Насколько я понял из BCLA, использоваться для разработки её вполне можно.


  1. Randl
    29.07.2016 23:56
    +15

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

    Это скорее не простота, а минималистичность. Мне нравится минималистичность, но с ней важно не переборщить (крайний пример — брейнфак. хотя нет, крайний — boolfuck). С учетом повсеместного интернета, когда достачно помнить, что что-то сделать можно, а гугл подскажет как — переборщить очень просто.


    В go отказались от динамической загрузки библиотек — результат компиляции один большой исполняемый файл

    Какие у этого плюсы?


    В go нет warning-ов при компиляции. Любая некорректность или «многословие» — это ошибка компиляции.

    Каждый раз когда вместо простого и понятного хака приходится писать функцию на полэкрана, умирает один котенок.


    В go встроен автоформат кода на уровне самого языка. Есть только один каноничный вид кода на go

    И не дай бог мне его неудобно читать — сам виноват.


    Код на go на 20-30 процентов короче аналогичного на яве (там просто не лишних слов, например, нет точки с запятой в конце каждого предложения, нет круглых скобок в операторах условия или цикла etc)

    У меня такое ощущение, что где-то в мире сидят программисты, чье единственно ограничение — скорость набора, и вместо книг по программированию они ходят на курсы по скоростной печати. Остальные разницы в 20% не почувствуют, и это с Java — невероятно многословным языком.


    Короче, то ли реализация принципов сомнительная, то ли примеры.


    P.S. Пожалуйста, давайте не будем начинать холивар. Меня интересует Go, и это неплохой язык (как и большинство остальных). К сожалению статьи о нем на Хабре зачастую неоднозначные и вызывают кучу срачей.


    1. Grief
      30.07.2016 08:12
      +1

      Вы все грамотно написали, не холивара ради я лишь хочу варизить одну свою мысль. При сравнении языков программирования все величины относительны. Ничего не удастся привести к единой шкале просто потому что языки различны. Производительность? В какой момент времени, сразу после старта или после прогрева виртуальной машины? В каких условиях, под какой нагрузкой — слишком много условных переменных. Читаемость, понятность, поддерживаемость? Ну это вообще настолько субъективно, насколько возможно. Если бы это было не так, то не существовало столь большого числа языков на сегодняшний день. Кому-то нравится питон, кому-то больше по нраву руби. Кто-то вообще не считает интерпретируемые или выполняющиеся в ВМ языки настоящим языками. Да, возможно, история склонила определенные языки к определенным целям, условно, си — железо, перл — обработка текста, питон — математическое прототипирование и т.д. Но все же, популярность языка обуславливается свойствами, перпендикулярными всем вышеперечисленным. Мне кажется, что для того, чтобы прижиться, язык должен следовать тем же правилам, что и любой другой программный продукт. А для любого программного продукта в первую очередь важен маркетинг. Даже если продукт бесплатный. В первую очередь, важно, кто стоит за языком. Майкрософт, Гугл, Эппл или Гвидо. Здесь играет роль и психология, наверное. Но вообще, я хотел о другом сказать. Есть единственное исключение, позволяющее сравнить языки по-честному. И это — краткость языка. Речь, конечно, не идет об обфускации. Когда я изучил питон после джавы, я был удивлен, насколько короче можно записать то же самое. Почему это важно? Дело, разумеется, не в том, что программист упирается в скорость набора, а в том, что чем меньше связующего кода и лишних абстракций, тем яснее можно увидеть сам алгоритм, тем меньше приходиться тратить внимание на вещи, прямо не связанные с задачей. Да банально уставившись в экран кода, видишь больше, иногда в разы. Взять, например, геттеры-сеттеры явы, больная мозоль для многих и камень преткновения. Факт в том, что даже будучи автогенеренными, они создают огромное количество шума, который нужно учитывать. Или все эти public static final void… зачем они нужны? Короче говоря, для себя я решил, что краткость кода — одна из первостепенных по важности вещей.


      1. Sirikid
        30.07.2016 14:19
        +6

        Go явно не лучший язык с точки зрения краткости. Может Java и многословней, но её система типов мощнее и есть огромная куча языков которые можно использовать вместо неё — Scala, Kotlin, Clojure, а для ценителей даже Haskell (Frege).


      1. Idot
        30.07.2016 14:26
        +1

        единственное исключение, позволяющее сравнить языки по-честному. И это — краткость языка

        Вот потому-то и я мечтаю изучить APL — очень красивый и ёмкий язык!


        1. softaria
          30.07.2016 19:11
          +3

          Я бы сказал, что важна не краткость, а низкий уровень шума и простота восприятия.
          Мне нравится критерий, который сформулировал Grief — язык тем лучше, чем больше смысла я вижу на одном экране.
          При том, что код писал не я и я — не гений, а среднестатистический специалист.


          1. webkumo
            31.07.2016 19:17
            +1

            Так перл же тогда! На одном экране можно увидеть всю не самую простую программу! Весь её смысл! Вот только как вы её понимать-то будете после этого?


            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 по данному критерию будут оценены не очень высоко.


              1. Randl
                31.07.2016 19:51

                Чтобы читать код, не надо быть гением. Надо знать язык.


                1. softaria
                  31.07.2016 20:03
                  +1

                  Чтобы читать такой код с большой скоростью и в промышленных объёмах, надо быть именно гением.
                  Большинство людей тоже сможет его прочитать, но мы затратим на это слишком много усилий.
                  Язык — прежде всего инструмент. В идеале, человек должен иметь дело исключительно со сложностью своей задачи, а не с дополнительной сложностью, привносимой языком.


                  1. Sirikid
                    31.07.2016 20:49
                    +3

                    Как раз таки Scala и подобные языки позволяют записывать сложные математические абстракции практически без лишнего шума со стороны языка.
                    Randl, а чтобы читать и понимать нужно знать предметную область.


                    1. softaria
                      31.07.2016 20:55

                      Поэтому у них есть своя ниша. Для которой они — прекрасны.


                  1. vadim_shb
                    31.07.2016 23:17
                    +2

                    У scala есть такая проблема. Многие библиотеки, в том числе стандартная, написаны очень непросто. Это или легаси, или описания DSL, удобных для применения сторонними разработчиками. Команда EPFL над этим работает, и потихоньку улучшает ситуацию. Многие вещи переписывают с нуля. Вводят дополнительные правила компиляции не позволяющие творить жесть в коде. Радует то, что во время разработки заглядывать в подобный код приходится крайне редко. А свой код можно держать в абсолютно читаемом виде. То есть работе это не мешает.


              1. solver
                31.07.2016 23:28
                +2

                «Можно» не означает «Нужно обязательно»
                Все пользуются ножами на кухне для резки продуктов.
                А ими ведь можно порезать себе пальцы… но как часто реально люди это делают?
                Одна из прелестных и сильных сторон Scala, как раз в разделении прикладной разработки и библиотечной.
                Для прикладной разработки все эти навороты не нужны.
                Эти навороты пишут ребята «семи пядей во лбу» и они их читают в лет.
                Они делают библиотеки для не таких опытных разработчиков.
                И это очень хорошо, что профи используют хорошие навороченные перфораторы, а не зубило с молотком.
                В Go же все вынуждены пользоваться зубилом и молотком. Да, это проще, да, это понятнее.
                Но все это напоминает старый анекдот «Пилу точить некогда, пилить надо».


              1. senia
                01.08.2016 01:01
                +4

                В этом коде, кстати, читать вообще нечего.
                Это же из shapeless наверняка. И читается, при знании shapeless, без проблем.
                В scala (особенно в shapeless) встречается сложный для понимания код, но это не тот случай.


        1. kuftachev
          31.07.2016 18:43

          По компактности, с Perl вообще мало что рядом сможет стоять, но как-то на нем пишут в основном администраторы.


    1. Falstaff
      30.07.2016 08:12
      +2

      Справедливости ради, с недавних пор динамическая загрузка в Go так-таки появилась. Плюс статической компоновки по умолчанию — это то, что получаются самодостаточные бинарники, которые зависят разве что от libc. На практике получается очень приятно, что можно отгрузить куда-то один файл и быть достаточно уверенным, что он не упадёт из-за неудовлетворённой зависимости.

      С автоформатом — да, если кто-то предпочитает другой формат, с Go получится неудобно. С другой стороны, приятие формата суть дело привычки. Вообще, в Go много крутилок и кнопочек принесли в жертву богу быстрой командной разработки — там всё сделано ради того, чтобы только что пришедший в команду джуниор или интерн начал быть эффективным на третий день вместо того чтобы неделю лупать глазами на непривычный формат кода, ещё неделю чертыхаться на отвергаемые (отформатируй согласно гайдлайнам проекта и приходи снова!) коммиты и подобные вещи. Я не берусь спорить, правильно это или нет, но определённая логика в этом есть.


      1. RomanPyr
        30.07.2016 11:48

        К слову сказать, писать Go код можно любым удобным для себя форматированием. Главное Git-хук на go fmt поставить.
        И тогда гошное форматирование будет на уровне автозамены CRLF.

        Читать да, только в каноничной форме :)


      1. Randl
        30.07.2016 16:01

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

        Статическая компоновка есть и в других языках. Смысла запрещать динамическую я не вижу.


        чтобы только что пришедший в команду джуниор или интерн начал быть эффективным на третий день вместо того чтобы неделю лупать глазами на непривычный формат кода, ещё неделю чертыхаться на отвергаемые (отформатируй согласно гайдлайнам проекта и приходи снова!) коммиты и подобные вещи.

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


        1. Falstaff
          30.07.2016 16:25

          Статическая компоновка есть и в других языках. Смысла запрещать динамическую я не вижу.

          А кто-то запретил? В Go есть динамическая компоновка (я вроде бы упомянул ответом выше), статическая там просто по умолчанию.

          По поводу форматирования — ну хорошо, чужой код вы прогоните через автоформатирование и будете читать так, как вам нравится. Но писать-то вам код придётся в соответствии с гайдлайнами того проекта, куда вас позовут. Или вы конвертируете и туда и обратно? Переформатируете всё написанное перед коммитом? Кстати, если что, с Go вам тоже никто не мешает так сделать. Просто есть официальный стандарт оформления и есть официальная утилита, которая форматирует. На вашей машине никто вас не заставляет ими пользоваться, дело хозяйское.


          1. Randl
            30.07.2016 16:38
            +2

            А кто-то запретил? В Go есть динамическая компоновка (я вроде бы упомянул ответом выше), статическая там просто по умолчанию.

            Я так понял, что изначально ее не было.


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

            То есть это не требования, а рекомендации? Но тогда все равно каждый будет форматировать как ему угодно. Возникает ощущение, что Go — язык непонятных искусственных ограничений.


            1. Falstaff
              30.07.2016 17:16

              Изначально не было. Ну так и язык относительно новый, во многих языках изначально много чего не было. Её не запрещали, её просто не сделали сразу. Вопрос приоритетов. Питону необходимость везде тащить рантайм и отсутствие динамических библиотек (хотя вроде уже можно что-то такое с Cython сделать? пусть знающие поправят) не мешает в топе TIOBE висеть и пользоваться народной любовью.

              Да, это не требования — не ограничения — а рекомендации. Поэтому я не совсем, признаться, понимаю, откуда ощущение взялось. Тут фокус в другом — есть такая штука как сила умолчаний. Если в языке из коробки есть официально рекомендованный стиль оформления и даже утилита, то в сообществе создаётся тренд, и очень немногие от него отходят. Получается, что и волки сыты (можно форматировать как угодно, если есть желание), и овцы целы (подавляющее большинство кода всё равно в стандартном единообразном стиле). Это просто психологический приём, чтобы большинство разработчиков безболезненно и быстро миновали фазу «так, в каком стиле мне начать писать код» и начали писать собственно код.


              1. grossws
                30.07.2016 17:44
                +2

                Да, это не требования — не ограничения — а рекомендации.

                Тогда странно выглядит то, что сначала очень старательно продавали статическую линковку как killer feature. Удивительное будет время, когда найдут какой-нибудь приятный баг где-нибудь в crypto. Сколько народу не пересоберёт (учитывая, что используют glide/gob далеко не везде), а сколько — забьёт?


                1. Falstaff
                  30.07.2016 18:05

                  И сейчас продают, и, по-моему, правильно продают. Killer feature в общем-то не сама статическая линковка как таковая, а то что она получается сама, по умолчанию, без каких-либо ментальных или физических телодвижений. Это всё та же сила умолчаний — у статической линковки есть плюсы, но чтобы использовать её в других языках, надо поработать, а тут получается бесплатно.


                  По поводу багфиксов — это старый спор, и я не думаю, что там есть какая-то правда. Это больше спор о том, кому быть виноватым — майнтайнерам пакетов с библиотеками, майнтайнерам приложений, или вообще нерадивым админам, которые ничего и никогда не обновляют. Если так подумать, то с тем же успехом можно накатить обновление библиотеки с незамеченным zero day (а может и с нарочно внесённым), и моментально все динамически слинкованные приложения становятся уязвимыми. Мне кажется, там проблема вообще в другой плоскости лежит.


                  1. grossws
                    30.07.2016 18:15

                    Тут рядом ещё ходит проблема невоспроизводимых билдов благодаря утилите go get, которая местами усиливает (более новая версия в репозитории может оказаться несовместимой и софт оставят необновлённым), местами — ослабляет (go get принесёт последнюю версию зависимости) вышеописанную проблему. Ну и всё это надо помножить на реальное разнообразие: кто-то вендорит зависимости, кто-то говорит "дёрните go get ..." при сборке; кто-то предупреждает о необходимости чистого GOPATH, кто-то предполагает, что он у вас единственный и вы будете использовать те же версии библиотек, что и в других своих проектах.


                    Меня лично радует, что glide пошёл в массы, но это очень субъективная штука, т. к. я на go не пишу, то, по сути, рассматриваю проблемы с точки зрения мейнтейнера, а не разработчика.


                    1. Falstaff
                      30.07.2016 18:53

                      Да, это больной момент у всей экосистемы. :( Зря на потом оставили. Я думаю, что вендоринг если не решит проблему, то хотя бы однородной сделает. Кстати, спасибо за наводку на glide, я пользовался gb-vendor, но glide выглядит хорошо (я тоже ничего на Go по большому счёту не пишу, но быть в курсе стараюсь).


                      1. softaria
                        30.07.2016 18:55

                        glide и работает хорошо, не только выглядит


                  1. Randl
                    30.07.2016 19:58

                    без каких-либо ментальных или физических телодвижений

                    Я пишу на С++, телодвижения сводятся к указанию пути к библиотеке и подключению заголовка. Куда уж проще?


                    1. Falstaff
                      30.07.2016 20:26
                      +3

                      Я тоже пишу на C++. Добавьте телодвижения автора библиотеки, который обеспечил возможность сборки статической библиотеки, и майнтайнеров пакетов, которые собрали её под нужную архитектуру и дистрибутив и доставили вам. :) Представьте, что в репах статической библиотеки нет (или вообще нет). И автор не предусмотрел сборку статической библиотеки (или вообще чего-нибудь толкового, или всё зависит от экзотичной системы сборки с запутанными и хрупкими конфигами). Мне в целом нравится, на чём я пишу, но мне кажется, что «куда уж проще» — это не про сборку и зависимости в C++. :)


                    1. OnYourLips
                      30.07.2016 22:27
                      +1

                      У вас были программы покрупнее, чем те, которые требуют всего одну библиотеку?

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

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


                      1. Randl
                        30.07.2016 22:48

                        Были, но они подключались по одной в процессе разработки. Больше получаса на поиск библиотеки с нужным функционалом, её сборку и подключение уходило редко.


                        Хотя если их несколько сотен, то и правда уйдет неделя.


                    1. sleeply4cat
                      30.07.2016 22:39

                      А что сейчас пишут на плюсах?
                      Прочитал «21 день», пока в отпуске был. Теперь меня терзают мысли про то, что с этим языком что-то серьёзно не так. Начиная с невозможности получить размер массива по указателю, хотя по логике он должен храниться в аллокаторе памяти, и до странной магии ручной расстановки меток виртуальных функций, которое, как мне кажется, компилятор вполне может делать сам. Всё это выглядит как хождение по заряженным арбалетам: никогда не знаешь, какой выстрелит. Это я что-то делаю не так, или язык действительно безнадёжно затянут в бездну обратной совместимости?


                      1. Randl
                        30.07.2016 23:00
                        +2

                        image


                        Если серьезно, то на плюсах пишут там, где нужна максимальная производительность. Несмотря на все его недостатки (а каждый находит десяток-другой своих), реальной альтернативы нет. Возможно, ей станет Rust.


                        З.Ы. В С++ есть std::array и std::vector, зачем пользоваться сишным массивом?


                        1. sleeply4cat
                          30.07.2016 23:09

                          Да просто 21 день — единственная книжка на русском языке с элементами С++11, которую нашёл перед уездом.
                          Про array знаю, просто привёл пример того, что на самом начальном уровне меня покоробило.


                      1. DarkEld3r
                        01.08.2016 12:53

                        или язык действительно безнадёжно затянут в бездну обратной совместимости?

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


                        В более новых языках типа Rust действительно многое проще (в том плане, что компилятор даст по рукам, если что), но суть остаётся той же: такие решения приходится принимать самому: если нужные виртуальные функции, то используем трейт-объекты и т.д.


                      1. 0xd34df00d
                        03.08.2016 01:33

                        Пишу высокопроизводительный код с матаном. Упираюсь при молотиловке чисел в производительность памяти. Хорошо.

                        Размер массива по указателю, впрочем, получать особо не нужно было. Да и как компилятор метки виртуальных функций расставить может, если полной информации о всём дереве наследования в общем случае у него может и не быть?


            1. shytikov
              30.07.2016 17:23
              +2

              Там всё плохо… Есть динамическая линковка — опция компилятора -dynlink. Это, насколько я понимаю, вызов кода из сторонних so и dll. Но свою динамическую библиотеку создать на Go — нельзя. И также нельзя подгрузить в рантайме произвольную библиотеку и вызвать из неё функцию.


              Другими словами, реализовать плагины в программе просто невозможно. И это главная проблема сейчас, как по мне. Это тормозит развитие http://gogs.io/, чтобы решить эту проблему ребята из http://caddyserver.com/ написали своё решение, которые перекомпилирует исходники с нужными модулями по выбору пользователя...


              Вот, к примеру, один из тасков о динамической загрузке. Закрыт. Заброшен: https://github.com/golang/go/issues/13751


              1. 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/


                1. shytikov
                  30.07.2016 17:58
                  +1

                  Но можно ли эти so или dll загрузить обратно в Go динамически? Вызвать функцию, а потом выгрузить из памяти?


                  Как я могу реализовать систему плагинов к моему приложению на Go без перекомпиляции оного?


                  1. Falstaff
                    30.07.2016 18:35

                    Именно чтобы руками, как с dlopen() или LoadLibrary()? С этим пока не очень просто. В принципе, насколько я понимаю (поправьте, кто это дело ковырял), можно загрузить через cgo. Код получается, мягко говоря, некрасивый, и не уверен, как сделать на не-POSIX платформе, но в целом должно работать. Что-то вроде такого:


                    // #cgo LDFLAGS: -ldl
                    // #include <dlfcn.h>
                    
                    import "C"
                    
                    // ...и дальше по тексту, handle := C.dlopen(...) и прочее.

                    Насколько удобно будет так делать развесистую систему плагинов — не знаю, надо пробовать и смотреть. Ну и, понятно, портируемость пострадала.


                  1. ardente
                    31.07.2016 18:43

                    Можно с помощью стандартного пакета syscall.


    1. QtRoS
      30.07.2016 08:50
      +11

      А я вообще не соглашусь с тем, что код на Go короче. Я пробовал, получилось более многословно, максимально приближено к C в плане последовательности действий, разве что очисткой памяти занимается сам рантайм.


  1. zim32
    30.07.2016 00:39
    +2

    >>Но очень быстро все уперлось в производительность.
    >>На одном сервере можно было запустить не более 300 клиентов.

    Я конечно извиняюсь, но думаю после этого можно не читать дальше. А в го у вас сколько клиентов получилось? 310?


    1. DragonFire
      30.07.2016 00:40
      +8

      Статью не читаю, комментарии пишу. Автор же написал что 2500


      1. zim32
        30.07.2016 00:43
        +9

        Ну т.е. после того как он стал использовать профилировщик (который никто ему не мешал использовать на джаве) он оптимизировал приложение. Это явно плюс языка go

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


        1. DragonFire
          30.07.2016 00:46
          +1

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


          1. zim32
            30.07.2016 00:52
            +6

            Потому что заявления — я написал сервер на джаве и он обрабатывал всего 300 клиентов (без тех. подробностей) это какая-то софистика.
            А я вообще использовал nodejs который обрабатывал пол миллиона клиентов, так что давайте все использовать nodejs )


            1. Moxa
              30.07.2016 02:05
              +1

              мне как-то скучно было и я на жавоском сервере на домашнем компе поднял 2 миллиона активных соединений, потребовалось 10гб оперативы, но старенький амд осилил ^_^


              1. zim32
                30.07.2016 02:13
                +3

                Ну а на го вы подняли бы примерно 16млн ;) судя из статьи


                1. softaria
                  30.07.2016 09:11
                  -5

                  Если там просто пустые соединения, то разницы бы не было.

                  Если сервер имеет сложную логику и «тянет» мало клиентов, то вывести его на нужный уровень производительности в go займет существенно меньше времени, чем выполнение той же задачи в java.

                  (Хотя, разумется, это возможно и в java и вообще на любом языке)


            1. softaria
              30.07.2016 08:18

              Сервера бывают разные. Ваши полмиллина клиентов — это игровые клиетны в реальном времени, как у меня?

              Кроме этого, вы не захотели понять суть статьи. Она не о том, что go — лучший язык.
              И не о том, что в ява нет профайлеров.
              Я сравнил усилия, которые от меня потребовали языки, чтобы сделать одно и то же. Go в данном случае потребовал в разы меньше.


              1. RaaaGEE
                31.07.2016 18:42
                +3

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

                Да ладно? Вы даже не пытались профайлить в джаве, о каких таких «потребовал в разы меньше» можно говорить?


                1. SirEdvin
                  31.07.2016 18:44

                  Как я понял, у автора «потребовал в разы меньше усилий» процесс профилирования, собственно.


                  1. softaria
                    31.07.2016 18:55

                    Не только он. Существенная экономия была достигнута за счёт профилирования и за счёт ловли race conditions.
                    Несущественная — за счет меньшего объема кода.


                    1. SirEdvin
                      31.07.2016 18:56
                      +4

                      Комментарий на который я ответил, как бы подразумевает, что вы не можете сравнивать сколько вы времени сэкономили, потому что профилировать код на Java вы даже не пытались.

                      Поэтому в статье у вас и получилась экономия только на том, что вы быстрее освоили один профайлер, чем другой.


                      1. softaria
                        31.07.2016 18:57

                        Ответил ниже. Могу. Потому что неоднократно ранее делал это с другими проектами.


                        1. SirEdvin
                          31.07.2016 19:05
                          +7

                          Хм, вот тут я вас не очень понимаю.
                          Если вы уже делали профилирование на других проектах, то у вас уже должны быть достаточные навыки для работы с профилированием в Java, что бы не писать о том, какое оно сложное и не понятное.

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

                          Так же, непонятки с профилированием, хотя за 18 лет, у вас точно должен был быть опыт профилирования хотя бы одного многопоточного приложения на java, а тулзов для race detector там полно.

                          Так же. вы тут где-то признавались с том, что не работали/не знаете ни одну библиотеку, для работы с серверами на Java, что еще более странно, с 18-летним опытом, если даже я, который впринципе не работает с Java в production, поработал с Netty.

                          Как-то немного многовато нестыковок.


                          1. softaria
                            31.07.2016 19:14

                            Достаточные навыки в чем-то не противоречат отношению к этом чему-то, как к сложному и неудобному.

                            Про сервер вы правы. Ранее я писал на java что угодно (начиная от web (бизнес системы) и кончая играми, Eclipse RCP или CORBA-SNMP gateway), кроме серверов реального времени, использующих Websocket. Этот сервер (а точнее — прототип) я написал очень быстро и без оглядки на performance. На этом этапе я определял что вообще должен делать этот сервер, по сути — проектировал игру. С технологией (библиотекой) я, кстати, действительно, ошибся.
                            Performance-ом собирался заняться на следующем этапе. Уже «предвкушал» приятную возню с VisualVM. Но наткнулся на описание профайлера в языке go (на который уже давненько с интересом посматривал). Описание понравилось. Решил сделать production вариант на go. Сделал. Опытом более чем удовлетворен.


                1. softaria
                  31.07.2016 18:56
                  -1

                  Вы путаете две вещи «я не пытался профайлить именно этот проект» (да, не пытался. Примерно знал во что оно выльется) и «я не пытался профайлить в java вообще» (такой опыт был, иначе не о чем было бы говорить)


  1. Ramzeska
    30.07.2016 01:03
    +2

    Го задалбывает приведением типов. И функции которые конвертнут из одного типа в другой всегда болтаются в разных библиотеках. Я был бы счастлив если был бы какой-то единый способ приведения стандартных типов. Есть странные вещи, например в условиях нельзя сравнивать целые и дробные, это очень бесит в циклах.


  1. nehaev
    30.07.2016 01:06
    +21

    Вот это проблемы у людей!

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

    Нельзя подключиться профайлером к удаленному серверу? Конечно можно, включаем JMX, пробрасываем порт и вперед. На самом сервере всегда можно заюзать консольные утилитки типа jmap, hprof и т.п.

    Race conditions — это действительно головная боль писателей многопоточных приложений, но далеко не всех. Некоторые все-таки знают про shared mutable state и избегают его, используя либо стратегию share-nothing (каналы в Go, Akka — в Java), либо функциональное программирование (переход на immutable).

    Стоит ли ява программисту полностью переходить на go? Нет.


    А вот с выводом-то особо и не поспоришь :)


    1. softaria
      30.07.2016 08:48
      -12

      Ваша мысль выглядит примерно так «Нельзя удалять гланды автогеном? Конечно, можно! Просто надо делать это через задний проход!»
      Я нигде не сказал, что в яве нет профайлера.
      Я сравнивал производительность инструментов (java + какой-то профайлер) vs (go + встроенный профайлер)
      Go в несколько раз выиграл в моём случае. Работать было быстро, удобно и приятно.


  1. AterCattus
    30.07.2016 01:15
    +7

    Глаз сильно зацепился за это

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

    Это ж насколько сильно нужно гадить в хип, чтобы заметить работу GC? Это точно не про Java?


    1. Laney1
      30.07.2016 08:19

      в go до недавнего времени применялся сборщик «stop the world», без ручного тюнинга паузы могли доходить до нескольких секунд. Но потом GC полностью переписали (сделали конкурентным), и сейчас все должно быть хорошо. Если интересно, то погуглите, на хабре есть несколько статей на эту тему.


      1. AterCattus
        30.07.2016 14:30
        +2

        Ну так мы и не про Go1.2 какой-нибудь сейчас говорим, верно? На 1.4 еще помню какие-то задержки на сотни мс, сейчас же на 1.6 даже 10-12 мс — это уже зачем-то много гадили в хип. Типичное время работы GC <= 1мс на наших проектах.


    1. softaria
      30.07.2016 08:22
      -6

      Нужно завести игровой сервер. Поднять там 2500 клиентов, каждый из которых будет отправлять в среднем 50 сообщений в секунду и получать примерно 750 (через web socket).
      Работа gc замечается в едва заметных глазу лагах при передвижении игровых объектов.


      1. Suvitruf
        30.07.2016 10:58
        +10

        Так это не gc скорей всего виноват, а вы с объектами, вероятно, неправильно работаете. Часто инстанциируете, нету пулов и т.п. У нас сервера игровые на java/C#, никаких лагов не наблюдаем связанных с gc.


        1. softaria
          30.07.2016 11:27

          Что касается объектов, то нет. Мы как раз оптимизировали здесь всё, что только можно было. В куче почти ничего не создаётся. Пулы есть.

          Возможные причины такой разницы:

          1) GC в go пока хуже, чем в java. До версии 1.5 был вообще ужасен. Но всё еще заметно хуже.
          2) Разная нагрузка на сервер. Наш получает от каждого из 2500 клиентов примерно 50 сообщений в секунду. Обратно отсылает примерно 750. Плюс имеет очень много межпоточных коммуникаций.
          3) Разные требования к серверу, обусловленные устройством самой игры. Если у нас влючить gc, появлется едва заметное дрожание кораблика раз в несколько секунд. Оно трудноуловимо, но создает ощущение, что с игрой что-то не так.


          1. AterCattus
            30.07.2016 14:44
            +1

            GC может и похуже, но:

            • escape analysis позволяет много чего оставить на стеке и уменьшить мусор в хипе;
            • многие типы нативны и хранятся как есть без лишних косвенных обращений, уменьшая нагрузку на GC при сборке

            И получается хорошо на больших хипах (десятки ГБ).

            P.S. У нас на пушилках, рассылающих около миллиарда пушей в сутки каждая (с огромной кучей логики, горутин, каналов, и т.п.), сейчас сборка gc занимает 12мс время от времени (и там даже sync.Pool почти нет).
            На более оптимизированных (пулы и профилировка наше все) демонах сборка редко когда даже 1мс занимает.


  1. ZOXEXIVO
    30.07.2016 02:02
    +19

    Смешно наблюдать за этими потугами недоразработчиков.
    Я из .NET, но тут я с Java.
    Сколько же вас развелось таких, кто не написав ничего серьезного и не имея за плечами нормального опыта, прыгают с языка на язык и успевают между этим писать поучительные статьи? Другие успевают преподавать с таким «богатым» опытом.
    Да, чувак, то что ты не умеешь пользоваться инструментами — это Java виновата, совершенно точно. проблема точно в ней!


    1. softaria
      30.07.2016 08:57
      -7

      Поясните каким образом вы оценивали мой опыт и почему решили, что я прыгаю с языка на язык?

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


    1. divan0
      31.07.2016 15:48
      -4

      Чем больше общаешься в англоязычных коммьюнити, тем страшнее читать вот такие комментарии, которые ещё и кто-то плюсует.

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

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


      1. softaria
        31.07.2016 15:51

        Большое спасибо за ваши добрые слова.


      1. SirEdvin
        31.07.2016 18:43
        +6

        Я все еще не понимаю, почему вам не нравятся такие комментарии.
        Они абсолютно справделивы.
        Go-коммюнити в Рунете уже достало писать такие статьи, где они сравнивают какой-то язык с Go, допуская в сравнении серьезные ошибки.

        По сути, всю статью можно было назвать: нагуглить инфу про профайлеру в Go проще, чем по профайлеру в Java.


        1. divan0
          01.08.2016 09:28
          +1

          Если вы не понимаете, почему оскорблять людей это не есть хорошо — я вам не объясню.

          Касательно статьи — пусть даже автор 1000 раз не прав, ему можно указать на ошибки уважительно и без оскорблений. Это будет правильней по всему пунктам. Почему-то в рунете это не сильно практикуется, увы.

          Опыт работы с профайлером в Go, кстати, и вправду, великолепен. Это не про «нагуглить» это про реальную продуктивность и затраченное время и когнитивные усилия от возникновения проблемы до ее фактического решения с помощью профайлера.


          1. SirEdvin
            02.08.2016 08:12

            Поговорив с автором я вытянул из него, что у него довольно богатый опыт с VisualVM и он от него устал. Это существенно дополнило мое впечатление о статье.


            Касательно статьи — пусть даже автор 1000 раз не прав, ему можно указать на ошибки уважительно и без оскорблений. Это будет правильней по всему пунктам. Почему-то в рунете это не сильно практикуется, увы.

            Можно сказать спасибо "интересным" статьям про Go ранее. Например, ту, в которой у компании крутились микросервисы на Java в Tomcat.


      1. ZOXEXIVO
        31.07.2016 21:42
        +3

        Если я в тексте вижу фразы — «я тут написал, а оно не работает, наверное такое на Java вообще не возможно написать», и еще приплести сюда какой-то недоразвитый язык и поставить его выше прекрасно зарекомендовавшего себя инструмента, который используют десятки лет, то готов многое высказать такому специалисту.
        И ведь, какой-нибудь школьник почитав этот «труд» реально подумает, что лучше Go ничего нет, а это уже просто диверсия какая-то.
        Иногда складывается впечатление, что это какие-то новые маркетинговые войны и реклама идет самыми грязными методами и просто внаглую


        1. sentyaev
          01.08.2016 02:30
          +3

          Помню, будучи «школьником», прочитал в книге или статье, уже и не вспомнить одну интересную мысль — «если у вас что-то не получается, или что-то не работает, не ищите проблему во фрэймвоке или библиотеках, ищите проблему в вашем коде».
          Почему-то мне это прям на подкорку засело.
          Так вот, за свои 10 лет работы, мне всего лишь один раз вствил палки в колеса IIS7, и то, просто потому, что я не знал одну его особенность по сравнению с IIS6. Мы с товарищем просидели пару дней дебажа ASP.NET.
          А ведь могли просто сказать — «это слишком сложно, или невозможно».


          1. divan0
            01.08.2016 09:39
            +2

            Это справедливо, если вы ограничены одной технологией в принципе. Но чем больше вы набираетесь опыта, тем больше понимаете, что выбор технологии (языка/базы данных/алгоритма/фреймворка/etc) это тоже часть работы инженера, и едва ли не важнейшая.

            Ограничивая свои знания одной технологией, вы повышаете свой knowledge debt, который будете выплачивать тем, что будете менее продуктивны. Вы могли бы точно так же зафанатеть по фортрану и считать, что те, кто предлагают вам другие языки «просто недостаточно хорошо разобрались» в фортране. Нет, нет и нет. Это ваша ответственность максимально объективно владеть ситуацией, знать плюсы и минусы технологий, уметь использовать как-минимум основные из них и уметь выбирать нужный инструмент для нужной задачи.

            Религиозный фанатизм тут к добру не приводит и понижает ваш уровень как специалиста очень существенно.


            1. iqiaqqivik
              01.08.2016 09:44
              +2

              Безусловно, просто го — это гигантский прыжок назад по сравнению с джавой в сегодняшнем мире. Овладевать языком имеет смысл тогда, когда он _лучше_, а не когда он _проще_.

              Ну, если, конечно, нет цели устроиться чернорабочим в гугл.


              1. divan0
                01.08.2016 12:53

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


                1. iqiaqqivik
                  01.08.2016 13:22
                  +3

                  > субъективные рассуждения про «сложнее значит лучше», с которыми я в корне не согласен

                  А-а-а-а, у вас с простыми силлогизмами, оказывается, проблемы. Я нигде не утверждал, что «сложнее — значит лучше». Я уж молчу про то, что никогда в жизни не принадлежал джава-миру, и писать код на джаве не стану, даже если от этого будет зависеть моя жизнь.

                  Просто я умею просматривать за ужином бенчмарки, а не доверять без разбору непонятно откуда взявшимся текстам.


            1. sentyaev
              01.08.2016 13:30
              +1

              Я не говорил, что есть технологии лучше или хуже.

              Но чем больше вы набираетесь опыта, тем больше понимаете, что выбор технологии (языка/базы данных/алгоритма/фреймворка/etc) это тоже часть работы инженера, и едва ли не важнейшая.


              Знать алгоритмы нужно, понимать разничу между разными типами БД тоже.
              Языки и фрэймворки… да какая разница? Вы действительно думаете, что есть хоть какая-то разница между RoR, JavaEE, ASP.NET и Spring? Ну да, некоторые фичи где-то из коробки, а где-то отдельной либой подключить, но по сути это одно и тоже.

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


          1. Randl
            01.08.2016 11:02
            +2

            В это веришь до первого пойманного бага в компиляторе :)


            1. sentyaev
              01.08.2016 13:22
              +1

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


              1. Randl
                01.08.2016 14:54

                Я вот об этом:


                если у вас что-то не получается, или что-то не работает, не ищите проблему во фрэймвоке или библиотеках, ищите проблему в вашем коде

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


                1. sentyaev
                  01.08.2016 15:06

                  А, так это совет именно для начинающих, а не тех кто дошел до того, что репортит баги компилатора.
                  Суть в том, что новички часто пытаются найти какой-то такой идеальный вариант где все хорошо, нет багов и почти не нужно писать код. И часто прыгают от одной технологии к другой. Типа пару лет пописали на .net, потом вышел nodejs и он почему-то лучше всех, теперь появился Go и нужно срочно переходить на него.
                  Причем все пытаются привести такой аргумента как продуктивность. А по сути, те же яйца, и через пару-тройку лет и пару-тройку сложных проектов точно так-же находятся баги в тулах и компиляторах.


        1. divan0
          01.08.2016 09:33
          -2

          приплести сюда какой-то недоразвитый язык

          Вы же понимаете, что с такой риторикой с вами общаться, как со взрослым человеком, нет смысла, правда?

          Если бы мне пришлось выбирать из двух кандидатов в свою команду, я бы однозначно выбрал автора статьи, а вас бы сразу в черный список занёс. Автор умеет осваивать новые вещи, умеет учиться, умеет делиться знаниями и не боится почувствовать себя новичком. Это очень ценно. Вы же фанатичны в одной технологии, не умеете адекватно общаться, обвешались в стереотипах и не умеете объективно смотреть на выбор технологии, как на один из важных элементов работы разработчика. По-моему, выбор очевиден.


          1. ZOXEXIVO
            01.08.2016 10:19
            +6

            Вы вроде взрослый человек, а ведетесь на какие-то, очень странные вещи.
            Вы видимо, тоже проскочили уровень, где начинаешь смотреть на ващи более трезво.
            С чего вы взяли, что человек выше будет учится и делать что--то лучше? Он язык приплетает для технологии, в некоторых случаях, это бывает оправданно. Такие люди будут вас доить, каждый год переписывая свое творчество на очередной язык.
            Go хорош для сетевой мелочи и не больше.
            Уж называть меня консерватором в технологиях просто смешно.
            Просто вы своими (Go) статьями, честно, уже достали.


            1. divan0
              01.08.2016 12:58
              -7

              Просто вы своими (Go) статьями, честно, уже достали.

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


              1. 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 корм закончился, больших жирных и зелёных просьба отойти. Готов только к нормальному диалогу.


                1. solver
                  01.08.2016 16:15
                  +6

                  Не смешной совсем. Это реально не смешно.
                  divan0 Какой-то ярый, непримиримый фанат Go.
                  Он приплетает все, что угодно в качестве аргументов против тех, кто сомневается в Go.
                  При чем технических аргументов очень мало. В основном он скатывается на личности и их качества.
                  При чем эта черта отмечается многими в разных Go тусовках. Такое ощущение, что в Go так принято.
                  Любой камент против Go вызывает бурную, просто неадекватную реакцию.


                  1. divan0
                    01.08.2016 16:27
                    -4

                    Я, наверное, что-то не понимаю, но я написал выше конкретно про то, что оскорблять людей — это неправильно, и строить дискуссию со слов «недоразвитый язык» не имеет смысла. Если вы в этом видите «любой камент», «неадекватную реакцию» и «скатывается на личности», то мы говорим на разных языках.

                    Если честно, то я очень рад, что почти не общаюсь в русскоязычном сегменте — очень отвык уже от такого уровня общения. Но автор статьи не заслуживает того, чтобы его оскорбляли. Человек поделился опытом, потратил время, написал пост на техническом ресурсе, и вынужден терпеть оскорбления. Со стороны выглядит дико и мне жаль, что здесь это норма. Мы люди, пишем софт для людей, мы можем находить общий язык, если соблюдать простые базовые правила общения. Во всем мире это работает, кроме рунета.


                  1. Iora
                    01.08.2016 16:36
                    +4

                    Где-то высказывали мнение, что это во многом из-за того, что Go был создан в Google Робом Пайком. И тут сложились два фактора: все, что делает «корпорация добра» по-умолчанию идеально, и всё, что делает такой человек, как Пайк — тоже идеально и все архитектурные решения, сколь бы нетрадиционными они ни были, по-умолчанию не могут быть подвержены критике из-за личности автора (если почитаете другие комментарии этого товарища, то там часто встречается что-то вроде «вы еще Пайка поучите», «Пайк знает, как правильно» и так далее).

                    Нет, Go выглядит довольно интересно и то, что он так бурно развивается — хорошо. Но уж больно его фанаты… фанатичны.


  1. grossws
    30.07.2016 02:14
    +4

    Профилировщики, которые я видел, требуют, чтобы их запускали на той же машине, что и сервер.

    JMC и VisualVM умеют подключаться к приложению по tcp. YourKit умеет подключаться удаленно. Какие профайлеры вы видели (и читали документацию к ним, ессно)?


    1. softaria
      30.07.2016 08:49
      -4

      Неаккуатно написал. Имел ввиду существенно различную сложность при использовании профайлеров java и go.


  1. grossws
    30.07.2016 02:19
    +15

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

    А за такое автора хочется бить тапком. Процессы — это сущность уровня ОС, они существуют не в языках программирования. То, что из ЯП можно дернуть соответствующий syscall (или библиотечную функцию) для порождения процесса не означает, что они "придуманы в языках программирования".


    1. Lure_of_Chaos
      30.07.2016 02:43

      Я думаю, это надо понимать так: сначала для многозадачных приложений приходилось использовать процессы уровня ОС, дергая соответствующий системный вызов.


      1. grossws
        30.07.2016 02:51

        Для создания треда в linux, например, обычно дергается syscall clone, если правильно помню. Создание нового процесса может выпоняться им же, просто с другими флагами, касающимися выделения нового стека, адресного пространства и т. п. Принципиального отличия с точки зрения ядра нет.


        Основной недостаток использования процессов — более дорогой IPC (хотя иногда выкручиваются через /dev/shm) по сравнению с использованием общей памяти разными потоками в рамках единого адресного пространства.


      1. softaria
        30.07.2016 08:23
        -1

        Именно так. Спасибо


  1. Ckpyt
    30.07.2016 05:09
    +1

    Автор!!! 300 клиентов на сервер!!! Вот это да!!!
    На плюсах писал сервер для ММОРПГ мне в страшном сне не могло такое присниться… минимум 10 000 при использовании самых жестких процедур
    .
    А хотите а скажу как можно создать эмулятор ЛЮБОГО количества клиентов на ОДНОМ клиенте?
    Берете вайршарк, пишете пакеты(еще лучше, свой сниффер), запускаете клиент, делаете нужные действия, пишете пакеты.
    А потом те же пакеты размножаете любым доступным способом. Вплоть до забивания пропускного канала :-) Так как вы автор, вы знаете где у вас в пакете хранятся уникальные для каждого пакета id и знаете как легко их можно поменять. Так что — это реально легко и просто :-)
    Почему свой сниффер лучше — понятно?

    Дайте, я еще угадаю: положение игроков рассылается не каждому по запросу, а от каждого каждому? В смысле, пришел пакет на изменение положения, это изменение разослали всем в зоне?

    П.с. это не в смысле «блин… какой дурак», а в плане «ооо!!! И я таким же молодым был» :-)


    1. webmasterx
      30.07.2016 06:12

      В смысле, пришел пакет на изменение положения, это изменение разослали всем в зоне?

      А как правильно? игры ни разу не делал


      1. Ckpyt
        30.07.2016 07:31

        У нас было так — в зоне храниться лог обработанных событий за последнюю минуту(т.е. не юзер2 жмет влево, а персонаж такой-то изменяет координаты на столько-то). Приходит пакет и говорит: «я хочу лог зоны с такой-то секунды и такой-то миллисекунды». Ему в ответ: «вот тебе родной», и сервером передается лог событий. Клиент, соответственно, запрашивает состояние зоны каждый раз, как поймал ответ, но не чаще чем через 250 мс от отправки предыдущего пакета, и не реже чем раз в четыре секунды(udp-пакеты могут теряться). Т.е. что пинг 50, что пинг 250 — без разницы.
        Почему это лучше? Потому что у клиента пинг может достигать до трех-четырех секунд… и он все равно будет видеть все, что происходило.
        У нас время жизни клиента без ответа было 15 секунд. Т.е. если от клиента не было ни одного пакета за 15 секунд, он вышел и должен заново проходить авторизацию. Этого хватало на самые плохие пинги(вроде, на Камчатке был клиент, но сейчас уже не уверен, где-то в дальних гребенях со стабильным пингом в три секунды).
        При этом, когда идет рассылка любых изменений всем в зоне, количество пакетов растет квадратично в зависимости от количества клиентов.


        1. softaria
          30.07.2016 08:27

          Как вы представляете многопользовательский шутер с временем жизни клиента без ответа в 15 секунд?


          1. Ckpyt
            30.07.2016 09:25

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

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


            1. softaria
              30.07.2016 09:29

              Если от него перестали приходить пакеты, его коннект убивается сервером (примерно, через секунду)
              Думаю, наши игры очень разные. Моя больше всего похожа на agar.io/slither.io.
              Там всё очень быстро происходит. 15 секунд — неприемлемо огромный интервал


              1. Ckpyt
                30.07.2016 09:36

                Да, я, с моими пингами, не смог поиграть ни в одну ни в другую :-)


    1. Vest
      31.07.2016 12:31
      +1

      Позвольте спросить у вас, почему вы выбрали способ именно «пересылки/повторении» трафика на свой сервер?

      Ведь наверняка при планировании архитектуры игры, вы могли бы заранее создать инструменты генерирующие эти самые запросы. Например, клиент использует некоторую библиотеку, которая отправляет/принимает запросы, потом её подготовить (можно урезать), и после вызывать нужные методы в большом количестве и с нужными параметрами.

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

      Спасибо за ответ.


      1. Ckpyt
        01.08.2016 21:34
        +1

        Во-первых, судя по статье, я подумал, что автор не очень опытный разработчик. И потому я посоветовал самый просто способ. Ну, на мой взгляд :-)
        Во-вторых, исследование СВОЕГО трафика — это одна из вещей, которой нужно заниматься при оптимизации клиента, о которой мало кто помнит.
        В-третьих, инструмент генерации пакетов так же нуждается в поддержке. Я понимаю, что в идеале правильнее всего было бы сделать «идеального бота» — выбирающего рандомные направления и жмущего рандомные кнопки из числа осознанных комбинаций. И соответственно, советовать писать его с нуля молодому(как я думал) программисту — не надо.

        Ну и в-последних: описанная мною фигнулька пишется часа за два-три в худшем случае… А вот с пакетогенераторам придется повозиться.

        Вот где-то так вот.


  1. Bringoff
    30.07.2016 08:07
    +12

    Что я понял из статьи: "Мне было нечем заняться, так что я решил выбросить шмат работы и переписать сервер на Go, потому что там есть встроенный профилировщик".
    Изначально у вас на Go получилось 20 клиентов, после профилирования 2500, то есть, на минутку, в 125 раз (!) больше.
    Вы не думали, что осиль вы профилировщик на джаве, у вас бы могло выйти ~37500 клиентов? Ну, или даже если бы вышло 2500, что всего в 8 раз больше первоначального (с таким размахом в Go-коде я не удивился бы), усилий пришлось бы приложить заметно меньше.


    Да, никогда от хороших java-разработчиков не слышал "ява".


    1. softaria
      30.07.2016 08:31
      -2

      Что я хотел сказать статьёй. «Написание определенных приложений занимает на go в несколько раз меньше времени и усилий чем на java. В том числе за счет более удобных инструментов.»


      1. sentyaev
        30.07.2016 23:58
        +2

        Я считаю это больше зависит от опыта и знания платформы. Т.к. по сути Go и Java языки одного уровня. Понятно, что на Go писать веб-сервер удобнее чем на Assembler.
        А то, что встроены инструменты или нет, это уже не имеет большого значения.


        1. softaria
          31.07.2016 14:44
          -1

          Согласился бы. Но вот на java я пишу 18 лет, а на go к тому моменту не писал вообще.
          Но на go таки вышло быстрее. Причем очень существенно.


          1. sentyaev
            31.07.2016 15:22
            +2

            Так именно это и вызывает сомнения.
            Вот например у меня чуть больше 10 лет опыта в .NET, и как-бы мне ни нравился какой-либо новый язык, я не могу быть на нем продуктивным. Т.к. дело-то не в языке, а в платформе, экосистеме, библиотеках и доступных инструментах, плюс мой опыт и знание всего этого.
            Я все это время занимаюсь веб-разработкой, причем примерно 90/10 если говорить backend/frontend, так даже по прошествии 10 лет я не могу сказать, что я хороший фротэндер (хотя последние пол года делаю проект на Angular2, и думаю еще через пол года, год у меня будет очень хороший уровень).

            Не важно какой язык выбрать (C#, Java, Python, Kotlin, Go и т.д, я имею ввиду языки одного уровня), важны ваши знания того, что сформировалось вокруг этого языка/платформы.

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


            1. softaria
              31.07.2016 15:28
              -4

              Продуктивность складывается из вашего опыта и знаний и удобства и мощности языка (в том числе, применительно к конкретной задаче).
              Это легко можно увидеть на примере — человек X потратил много лет на изучение ассемблера.
              У него стоит задача написания веб сайта.
              Что будет для него эффективнее — писать сайт на ассемблере или на .NET?
              Я думаю, .NET будет лучшим выбором.
              Здесь я столкнулся с похожей ситуацией — увидел класс задач, который решается на go настолько удобнее, что несмотря на мой опыт на java я теперь предпочитаю для таких задач go.


              1. sentyaev
                31.07.2016 16:10
                +1

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


                Это понятно, и про это я уже писал. Но Go и Java суть одно и тоже, просто синтаксис разный.

                Просто все ваши ответы на вопрос «Чем же Go лучше», вы отвечаете «Лучше чем другие языки». Согласитесь, что это сомнительный аргумент.
                В свою очередь хочу заметить, что ходить в джинсах синего цвета гораздо удобнее, чем в красных)))


                1. softaria
                  31.07.2016 18:13

                  Но Go и Java суть одно и тоже, просто синтаксис разный.


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


                  1. 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 таких инструментов предостаточно?


                    1. softaria
                      31.07.2016 19:59
                      +1

                      Просто Google нужен был свой. Чтобы решать свои задачи.


                      Из этого можно сделать вывод, что есть какие-то задачи, для которых go подходит лучше других языков. (Ну или, что google таки создал его зря, как следует не разобравшись).
                      А раз так, значит go отличается от других не только синтаксисом.

                      Мне бы хотелось понять, что это за задачи.


                      Цитирую свою же статью: Какие задачи лучше всего решать на go? Создание многопоточных высоконагруженных серверных решений, в которых потоки много коммуницируют между собой.

                      Согласитесь, что в Java таких инструментов предостаточно?


                      Соглашусь. Предостаточно. Здесь речь скорее о философии языка. О том, что с точки зрения того или иного языка важно (а значит включено в набор стандартных инструментов, хорошо продумано и документировано) или просто есть (и, чаще всего создано третьими сторонами).
                      На любом современном языке можно сделать всё что угодно.
                      Разница в том, на чем язык предлагает сосредоточиться в первую очередь. В go профилирование и борьба с race conditions это, если хотите — first class citizens. В java — просто часть огромной экосистемы.


                      1. iqiaqqivik
                        01.08.2016 08:05
                        +1

                        > Из этого можно сделать вывод, что есть какие-то задачи, для которых go подходит лучше других языков

                        Абсолютно корректный вывод. Такая задача одна, и эта задача — упростить найм (Гугл нанимает так много сотрудников, что профессионалов в этих количествах взять просто неоткуда). Иными словами вот таких «я тут потыркался в java, что-то не взлетело, ну так сейчас перепишем на го и заживем». Го спроектирован таким образом, чтобы даже баран не мог сильно напортачить, и это — его единственная цель (и плюс).

                        Сеньор в _любом_ другом языке решит _любую_ задачу лучше, чем на го. Джуниор на го решит любую задачу лучше, потому что ему язык надает по рукам в нужных местах. Но за все нужно платить: пока у вас не пятьсот тысяч сотрудников, го — обуза.


              1. firsttimecxx
                31.07.2016 17:15
                +4

                >>Что будет для него эффективнее — писать сайт на ассемблере или на .NET?
                Подмена понятий.

                >>Я думаю, .NET будет лучшим выбором.
                Не верно, ибо подмена понятий.

                Никто не пишет сайты на .net. Никто не пишет сайты на языке — сайты пишут на готовом апи. И без разницы какой это язык, если ты вызываешь какой-нибудь интерфейс. Разница только в сахаре, но это не особо принципиально, да в современных ассемблерах сахара не меньше.

                Подлог заключается в том, что вы сравниваете пацана с .net, который на 99% состоит из готового веб-рантайма и пацана с асм, у которого рантайма нет. Но ведь .net-пацан этот рантайм не писал — точно так же асм-пацан может его написать, либо взять готовое.

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

                Реальный мир просто способствует продвижению этого мифа, ибо задачи на тех же сях решаются дольше. Но это следствие не того, что на сях «дольше», а просто задачи решаемые на сях сложнее. Живые сравнение Си вс жава не проводятся, ибо это не имеет смысла.


                1. softaria
                  31.07.2016 18:15

                  Это не подмена понятий а иллюстрация явления в его крайней форме.

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


                  1. firsttimecxx
                    31.07.2016 21:50
                    +3

                    В любой форме это сравнение не имеет смысла, ибо не является правдивым. Чистейшей воды подмена понятий «средства языка» с «готовые средства рантайма для реализации какого-то функционала». В данном случае в .net средства для веб есть по умолчанию, а у асм«а нет. И средства эти не уровня языка.

                    Сам же язык — это про удобство использования api и в редких случая для написания нового кода, но там кроме циклов и функций ничего нового особо не придумали.

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

                    >>значит у него есть ниша, где он лучше других.
                    Скорее наличие ниши и делает язык лучше, ибо он более специализирован, а не наоборот. И то не сам язык(в очень маленькой степени), а его рантайм/реализацию самого языка.

                    Лучше в смысле как язык, то тут не всё так просто. Лучше в одном — хуже в другом.


                  1. sentyaev
                    01.08.2016 02:32

                    Конечно подмена понятий, я изначально написал несколькими комментариями выше:

                    Я считаю это больше зависит от опыта и знания платформы. Т.к. по сути Go и Java языки одного уровня. Понятно, что на Go писать веб-сервер удобнее чем на Assembler.


          1. Slepetc
            31.07.2016 23:54
            +1

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


  1. alexkran
    30.07.2016 08:31

    Интересная статья, спасибо.
    Довольно адекватно расписаны возможности языка. Однако Go для совсем новичков я бы никогда не рекомендовал, учиться программировать на Go гораздо тяжелее, чем на Java, в силу того, для чего он разрабатывался и какие задачи должен выполнять, имхо.


    1. divan0
      31.07.2016 15:52
      +1

      Однако Go для совсем новичков я бы никогда не рекомендовал, учиться программировать на Go гораздо тяжелее, чем на Java

      Можно тут чуть подробнее? Почему «гораздо тяжелее»? Давно интересуюсь темой Go как первого языка программирования, и интересны мнения со стороны.


      1. SirEdvin
        31.07.2016 18:46

        Go не прививает, скажем, правильное ООП, и подвержен некоторым крайне сомнительным практикам, например, хранение метаданных в комментариях или кодогенерации.


        1. divan0
          01.08.2016 09:41
          -4

          правильное ООП

          Что это такое? И почему «неправильное ООП» сложнее новичкам, чем «правильное ООП».

          крайне сомнительным практикам, например, хранение метаданных в комментариях или кодогенерации.

          Принимаю аргумент про «сомнительные практики» — в других языках это действительно были хаки и сомнительные практики, но в чём проблема у новичков с этим?


          1. SirEdvin
            02.08.2016 08:16

            Что это такое? И почему «неправильное ООП» сложнее новичкам, чем «правильное ООП».

            Скажу проше. В Go — нет ООП. Go — это процедурный язык. И то, что в Go можно писать в ООП-стиле не делает его OOP языком. Аналогичная ситуация в Java, никто не назовет Java функциональным языком, но писать в таком стиле там можно. А как показывает практика, процедурников крайне сложно научить потом ООП.


            Принимаю аргумент про «сомнительные практики» — в других языках это действительно были хаки и сомнительные практики, но в чём проблема у новичков с этим?

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


            1. iqiaqqivik
              02.08.2016 09:39

              > как показывает практика, процедурников крайне сложно научить потом ООП

              То есть, история вопроса нам как бы сообщает: в семидесятые годы прошлого века, когда мир вокруг состоял сплошь из процедурников, к нам явились марсиане и научили ООП. Так?


              1. SirEdvin
                02.08.2016 12:50
                -2

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


            1. Falstaff
              02.08.2016 09:55
              +2

              Справедливости ради, Алан Кей изначально вроде бы не думал о полиморфизме и наследовании как неотъемлемых свойствах ООП. Тема довольно размытая, поэтому категорично утверждать, что в каком-то языке нет ООП, а в другом есть — вряд ли конструктивно. Думаю, что «сильно отличается от повсеместно используемых практик» это максимум, что можно сказать, не рискуя уйти в холивар.


              Вообще, есть ли смысл абсолютных новичков учить объектно-ориентированной парадигме? Если говорить вот прямо о людях с улицы, без курса CS за плечами, без какой-то IT основы. Мне кажется, что они будут тяготеть к процедурному стилю, обрушить на них объекты или функциональное программирования — у них сразу интерес пропадёт.


              1. SirEdvin
                02.08.2016 13:00
                -1

                Вообще, есть ли смысл абсолютных новичков учить объектно-ориентированной парадигме?

                Смысл есть, так как 70-100% задач на рынке решается именно через ООП, потому что оно туда как раз и подходит. Скажем, я сталкивался с тем, что люди, которые много пишут в процедурном стиле не понимают, зачем им нужно вообще это ООП и получается их заставить его учить только поставить или довольно исскуственную задачу, в которой сложно обойтись без принципов ООП, или закинуть его в реальный проект, но это вызовет большие пробелы в дальнейшем.


                Справедливости ради, Алан Кей изначально вроде бы не думал о полиморфизме и наследовании как неотъемлемых свойствах ООП.

                Википедия, с ссылкой на книгу Т. Бадда (isbn 5887822708 в русском переводе) дает такой список правил, которые оговаривал Алан Кей:


                1. Всё является объектом.
                2. Вычисления осуществляются путём взаимодействия (обмена данными) между объектами, при котором один объект требует, чтобы другой объект выполнил некоторое действие. Объекты взаимодействуют, посылая и получая сообщения. Сообщение — это запрос на выполнение действия, дополненный набором аргументов, которые могут понадобиться при выполнении действия.
                3. Каждый объект имеет независимую память, которая состоит из других объектов.
                4. Каждый объект является представителем класса, который выражает общие свойства объектов (таких, как целые числа или списки).
                5. В классе задаётся поведение (функциональность) объекта. Тем самым все объекты, которые являются экземплярами одного класса, могут выполнять одни и те же действия.
                6. Классы организованы в единую древовидную структуру с общим корнем, называемую иерархией наследования. Память и поведение, связанное с экземплярами определённого класса, автоматически доступны любому классу, расположенному ниже в иерархическом дереве.

                Тут есть наследование.


                1. 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

                  Не было там ни полиморфизма, ни наследования.


                  1. SirEdvin
                    02.08.2016 14:18

                    Очевидно, от глупости, лени и не хватки времени.


                    Большое спасибо за первоисточник :)


                1. Falstaff
                  02.08.2016 14:36

                  С практической точки зрения — да, мотивация понятна: чтобы потом не переучивать для боевых задач. Я скорее говорю о ситуациии с людьми, которых в любом случае ещё рано закидывать в реальный проект — не интернов или джуниоров, а, скажем, детей, или просто впервые осваивающих программирование. Любопытно, есть ли тут кто-нибудь, кто детям преподавал. У меня очень маленький с этим опыт, будет нерепрезентативно.


                  1. Idot
                    02.08.2016 14:50

                    Детский Scratch — учит Объектно-Ориентированному Программированию.
                    Детский Logo — учит Функциональному Программированию.
                    — и то и другое дети вполне понимают.


                    1. Falstaff
                      02.08.2016 15:05

                      Лого вроде мультипарадигменный, нет? Тут скорее интерес с точки зрения опыта. Scratch — да, хороший пример.


    1. softaria
      31.07.2016 18:36

      Я правильно понимаю, что у вас был опыт наблюдения за новичком, который пытался начинать с go?
      Если это так, расскажите подробнее, пожалуйста.
      Я никаких проблем не вижу, но поскольку к моменту изучения go новичком не был, то мог что-то важное пропустить.
      А вопрос для меня, действительно важный — думаю о более широком применении go в нашей компании.
      В том числе и для юниоров.


      1. sentyaev
        31.07.2016 20:36

        Есть небольшой опыт обучения совсем новичка в программировании. Сначала выбрали Go, но как-то сразу не пошло (я не говорю, что я очень хороший учитель, но очень старался).
        Начали с самых основ, без языка по сути. Рассказал основы, порисовал немного. Вроде бы можно было приступать к первым шагам.
        Долго продвигались через такие понятия как переменная и функция.
        Первой же большой проблемой стало объявление переменных в Go и два варианта присваивания (это для начала решили пропустить и взяли только один вариант).
        Когда дошли до структур, столкнулись с тем, что человек не понимал как их создавать. Попытки объяснить проблему не решали.
        С методами было совсем плохо, просто было не возможно объяснить разницу между обычной функцией и методом.
        Про интерфейсы я совсем молчу.
        Через месяц решили не мучатся.

        Расчехлили Java, и буквально на второй день человек освоил классы, методы, и принципы ООП. Даже по глазам стало видно, что товарищь теперь все понимает, а не «тупит». Ну, вы же знаете этот горящий взгляд и желание быстрее что-нить накодить.

        Такой вот опыт.
        И мне кажется успех ООП как раз в этом, его понимают обычные люди.


        1. softaria
          31.07.2016 20:47

          Спасибо. Интересный опыт. Хотя, данных для статистики недостаточно.
          Вдруг это — особенность конкретного человека.


          1. sentyaev
            31.07.2016 21:01

            Согласен, один человек — выборка недостаточная.
            С другой стороны этот самый человек очень хорошо усваивает программирование, и, на начальном этапе, проблемы были именно с «философией Go» и его концепциями.

            Мне лично, Go тоже показался не самым простым языком. Т.е. первым я бы его точно не смог осилить.

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


            1. softaria
              31.07.2016 21:06

              Мне Go показался простым. Хотя привлёк не этим, а сдвигом «фокуса». Его авторы переосмыслили, что сегодня является важным в языке, а что — не очень. на мой взгляд, их вариант лучше подходит для решения актуальных задач.

              А вот смог бы я осилить Go первым или нет — фиг его знает. Именно поэтому очень инетересен опыт тех, кто пробовал.

              ему гораздо важнее решить задачу правильно, чем решить задачу в принципе.

              Проблема в том, что у каждого своё — «правильно».


      1. alexkran
        01.08.2016 11:44

        Для новичков будут проблемы в понятии самой концепции языка, не каждый новичок поймет как правильно выстраивать структуру приложения из интерфейсов и структур(хотя по мне так прикольная концепция вышла из этого). Потом Go-рутины, для новичка многопоточность это вообще страшная штука, которую просто так не понять с пары примеров, это куча опыта, которую и за год много не накопишь, новички не поймут пользы от многопоточности, Go-рутин, каналов и etc.

        И приподносится этот материал по странному. В плане если в Java/C#/C++, когда разговор доходит о многопоточности первым делом говорится для чего это нужно и когда используется, в Go же это одна из основных концепций, и тем самым для совсем новичков это осложняет дело еще сильнее.

        Плюс еще ограниченность в плане, как бы правильней сказать, видимости результата. Новичкам нужно видеть, как у них в программе банально произошли вычисления и они вывелись на экран, особенно все начинающие любят GUI и формочки, для чего Go не очень адаптирован, хоть и может. А если же язык показывает какие-то вещи, которые еще не дошли до молодого ума и он не видит результата то это веет смуту.

        Если у человека есть опыт программирования даже просто в плане обучения на каком-нибудь Ruby/Python/Java, ему будет в этом разобраться будет не так уже тяжелее. Имел опыт общения с Go после C++, и в целом неплохо.
        Go в целом язык ничего так, но не прям уж для запихивания во все дырки и не для совсем новичков. Это лично мое мнение.


  1. dimkss
    30.07.2016 08:31
    -3

    Спасибо за четкую, и по делу статью.
    Как вы думаете, Go ориентирован только на серверное использование, или на нем можно забацать приложение с окнами, графикой, и еще какими то финтифлюшками?


    1. softaria
      30.07.2016 08:32
      -1

      Сделать на go можно что угодно.
      Мысль в том, что серверные многопоточные приложения быстрее и удобнее делать на go.
      А для остальных особых преимуществ нет — дело вкуса.


      1. dimkss
        31.07.2016 12:09
        -2

        Спасиб.
        Имею некоторый опыт работы с java, поэтому статья очень в тему.


  1. Agonee
    30.07.2016 08:33
    +5

    Открой для себя JNI


    1. softaria
      30.07.2016 08:33
      +1

      Зачем?


      1. Agonee
        31.07.2016 07:40

        Перформанс. Статья ведь об этом.


        1. firsttimecxx
          31.07.2016 14:44

          Но ведь это не жава? С таким же успехом можно писать на си и вызывать из го, не?


        1. softaria
          31.07.2016 14:45

          Статья не об этом. Она о продуктивности разработчика.


          1. Agonee
            01.08.2016 06:09

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


  1. IllusionTurtle
    30.07.2016 09:36

    Для решения этой проблемы используются внешние инструменты — менеджеры пакетов.
    Один из лучших на сегодняшний день — glide.

    Зачем использовать стороннюю утилиту, если данная проблема уже решена на уровне языка — используйте директорию vendor (v1.5 experimental, v1.6 default)
    Кстати, директория vendor решила и ещё одну проблему о которой вы не упомянули, локальные импорты.


    1. softaria
      30.07.2016 09:37

      glide её использует
      Просто он позволяет не хранить сторонние пакеты в своей системе контроля версий.
      Каждый член команды может при помощи glide поместить в свою директорию vendor нужные версии сторонних пакетов.


  1. naething
    30.07.2016 09:38
    +8

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

    Если требуется поддерживать несколько тысяч клиентов одновременно, особенно при высокой частоте запросов как в онлайн игре, понятно что скорее всего придется использовать асинхронный ввод-вывод вместо традиционной модели «один поток на соединение». Тут, как говорится, и к гадалке (профайлеру) не ходи. Да, в Го это работает из коробки путем использования «горутин», ну а в Java можно использовать Netty.

    Проблема с запуском профилировщика удаленно в Java совершенно надумана. Достигается добавлением пары опций в JVM.

    Проблема с запуском нескольких тысяч клиентов тоже надумана. Зачем запускать настоящие клиенты, если можно с помощью того же Netty/NIO написать относительно несложную программу для нагрузочного тестирования, которая буквально с одного компьютера создаст достаточную нагрузку?

    И в конце концов, в Го вы все равно можете упереться в сборщик мусора или, скажем, странное поведение планировщика горутин. И что тогда, снова все бросить и переписать на C++?

    По-моему, шило на мыло. Выбросили существующий код и проверенную временем JVM ради «модного» языка из-за каких-то странных доводов.


    1. softaria
      30.07.2016 09:50
      -4

      > а в Java можно использовать Netty.

      Или VertX или Play или много чего еще.

      > Проблема с запуском профилировщика удаленно в Java совершенно надумана.

      Тут вы правы. Я неверно расставил акценты. На самом деле надо было сказать о простоте и удобстве работы со штатным профилировщиком go. По мощности он превосходит VisualVM и сравним с YourKit. По удобсвту работы — лучшее, что я видел вообще. Экономит много времени.

      > написать относительно несложную программу для нагрузочного тестирования

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

      > в Го вы все равно можете упереться в сборщик мусора

      Да. Его пришлось отключить вовсе. Точнее перевести в ручной режим. Сначала код был переписан так, чтобы минимизировать использование кучи. Потом автоматический gc был отключен и заменен на код, который запускает его вручную, если свободной памяти на сервере осталось немного. Перед таким ручным запуском все клиенты принудительно ставятся на паузу. Происходит это редко и для игрока такое поведение много луше частых небольших лагов.

      > Выбросили существующий код и проверенную временем JVM ради «модного» языка из-за каких-то странных доводов.

      Ради опыта. Я знал сколько времени занимает решение подобной задачи на java. Я подозревал, что на go потребуется меньше. Я убедился, что да, меньше. Раза в два. И теперь я буду решать такие задачи на go и экономить свое время.
      Этим вот опытом и поделился.


      1. naething
        30.07.2016 10:20
        +7

        Или VertX или Play или много чего еще.
        Ну странно наличие вариантов рассматривать как минус. Так же можно было вместо Го использовать Rust, node.js или много еще чего.

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

        Может быть вы и правы. И даже если выбор эмоциональный, то всегда хорошо, когда программирование приносит удовольствие. Особенно если проект небольшой и делается в основном на энтузиазме.


        1. softaria
          30.07.2016 10:35
          -2

          Ну странно наличие вариантов рассматривать как минус.


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

          Верю с трудом, особенно в долгосрочной перспективе, и тем более если есть опыт подобных проектов на Java


          Здесь сложно что-то возразить. У меня оно было так. Но каков в этом результате вес самого языка, моего проекта и моих личных предпочтений мне сказать трудно. Если есть опыт разработки таких проектов на java и если вас не раздражают VisualVM или YourKit, то, возможно, у вас будет другой результат.

          Единственное, на чем я настаиваю — если взять двух новичков и один станет изучать java + экосистему, а второй go, то проект, подобный моему, быстрее получится у второго при прочих равных.


          1. Suvitruf
            30.07.2016 11:03
            +2

            Наличие вариантов имеет свои минусы (порог вхождения) и плюсы (можно подобрать наиболее оптимальный).
            Если говорить о продуктивности разработки, то наличие ровно одного хорошего способа сделать что-то будет плюсом, так как сэкономит время.
            Отсутствие альтернатив во все времена приводило к монополии. Наличие конкурентов/альтернатив вынуждает авторов библиотек совершенствовать свои продукты.

            Единственное, на чем я настаиваю — если взять двух новичков и один станет изучать java + экосистему, а второй go, то проект, подобный моему, быстрее получится у второго при прочих равных.
            А если взять профессионала, то тот выберет java, так как на ней лучше писать долгоживущие проекты?


            1. softaria
              30.07.2016 11:37
              -1

              Отсутствие альтернатив во все времена приводило к монополии. Наличие конкурентов/альтернатив вынуждает авторов библиотек совершенствовать свои продукты.


              Вы привели еще один плюс наличия альтернатив. Только он не имеет отношения к продуктивности разработчика здесь и сейчас.

              А если взять профессионала, то тот выберет java, так как на ней лучше писать долгоживущие проекты?


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


  1. 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…

    Из всей статьи полезный и осмысленный только вывод…


    1. softaria
      30.07.2016 10:41
      +1

      Если уж Вы пытаетесь продвинуть мысль того, что go производительнее java в разрезе вашей задачи


      Вы неправильно поняли. В разрезе моей задачи производительнее не go, а программист, пишущий на go.
      Он справится с такой задачей быстрее, даже если ранее имел опыт программирования на java и не имел на go.


      1. ShadowsMind
        30.07.2016 10:58
        +2

        Т.е. в конторах пишущих игры ААА класса сидят дурачки, которые не знают, о том что программист на Go производительнее программиста на Java?! Тогда уж «в разразе Вашей задачи Вы пишущий на Go произовдительнее себя же пишущего на Java».


        1. softaria
          30.07.2016 11:11

          Т.е. в конторах пишущих игры ААА класса сидят дурачки, которые не знают, о том что программист на Go производительнее программиста на Java?!


          Нет. Там сидят большие сложившиеся команды, которые много лет пишут на java и имеяют массу наработок, которые переиспользуются в новых проектах. Для них стоимость перехода на другой язык огромна.

          в разразе Вашей задачи Вы пишущий на Go произовдительнее себя же пишущего на Java


          Если говорить совем строго, то да. Именно так. Но я рискну расширить это утверждение до следующего «в разразе моей задачи человек с 18летним опытом программирования на java и нулевым опытом на Go, пишущий на Go произовдительнее себя же пишущего на Java»


          1. fogone
            30.07.2016 12:20
            +11

            человек, который 18 лет разрабатывает на java и не знает о существовании возможности удаленного подключения профилировщика, вызывает подозрения


            1. DragonFire
              30.07.2016 12:29
              -2

              Вы то точно разрабатываете на java со вчера и уже знаете абсолютно все, мы не сомневаемся =)


              1. fogone
                30.07.2016 14:55
                +2

                Сомнения — признак критического мышления, а то, в свою очередь, признак здравомыслия


            1. softaria
              30.07.2016 12:29

              Вы правы. Не пойму, как я написал такое. На эмоциях, наверное. Очень раздражает меня VisualVM. Трудно найти что-то более неудобное.


              1. fogone
                30.07.2016 15:09
                +3

                Согласен с тем, что не всё в мире java идеально и в эпоху перемен хочется свежего воздуха, я и сам внимательно смотрю на котлин. Здорово, что этот глоток свежего воздуха пришелся вам по душе, но все-таки статья скорее эмоциональный выплеск об этом, нежели что-то полезное в техническом смысле. Было бы интереснее, если бы вы описали какие аналогичные средства вы использовали в обоих реализациях и что именно было удобнее, возможно рассказать об архитектуре серверной части игры, а такой холиварный формат неизбежно вызывает раздражение у читающих


                1. softaria
                  30.07.2016 17:41
                  -1

                  Это всё от лени. Я просто взял и опубликовал собственный рассказ на корпоративном семинаре.
                  По уму для хабра статью надо было перделать и писать примерно так: Вот уже 14 лет мы пробуем новые языки, чтобы не пропустить технологическую волну. До сих пор, ни один язык не выигрывал у явы в главном для нас параметре — в скорости разработки. Так было, пока не появился go.
                  Этот самый go выиграл по этому параметру на таком-то проекте. Если ваш проект похож, обратите внимание на go.
                  Тогда бы и холивара было бы поменьше.


                  1. solver
                    30.07.2016 20:07
                    +7

                    Холивара было бы поменьше, если такие статьи (саксес стори) по Go были более объективными.
                    А так они все как под копирку. Одни досужие домыслы и притягивания за уши. Без какой либо конкретики.
                    Добавьте сюда, по вкусу: вранье, передергивание или откровенное нубство в сравниваемой технологии (в данной статье про Java).
                    И получите типичный холивар.
                    Напишите нормальную статью. С примерами похожих задач.
                    Вот так делали на Java (и это должен быть реальный пример на современных подходах и библиотеках).
                    А вот так мы сейчас делаем на модном Go.
                    С описанием и цифрами. Что улучшилось в процессах. Что улучшилось в коде. Что там с багами и поддержкой. Что с рефакторингом и т.д.
                    Все вам огромное спасибо скажут.
                    А то вот таких вот домыслов «вилами по воде» в каждом бложике миллион.
                    Они ничего не улучшают, а только хуже делают.
                    Ибо оставляют больше вопросов, чем дают ответов.
                    А в отсутствии реальных фактов, люди начинают сплетничать и фантазировать на тему как оно там может быть…


                    1. softaria
                      30.07.2016 21:31
                      -1

                      Вы пишите о вранье, передергивании и нубстве и тут же требуете цифр, примеров и фактов.
                      Допустим я скажу, что аналогичная задача на яве заняла у меня X дней, а на go — Y (где Y<X), вас это убедит?

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

                      Проблема совсем не в фактах, а в неаккуратном позиционировании моей статьи. Многие тут посчитали, что я хвалю go и ругаю java, приводя в качестве (слабого) аргумента некую сомнительную, как вы сказали «success story». Я сам дал повод так понять эту статью неаккуратной расстановкой акцентов.

                      Где-то уже писал, что статья не про то. Она про: «ребята, смотрите, go гораздо менее требователен к вашему времени и усилиям по крайней мере на некоторых видах задач. Если ваши задачи схожи, то Go стоит попробовать. Возможно, вы получите некоторый profit.»


                      1. Randl
                        30.07.2016 22:17
                        +4

                        Оставьте цифры. Дайте пример с кодом или описанием архитектуры на Java и, соответсвенно на Go.


                        Без этого создается впечатление именно нубства (может это и не так) из-за 300 клиентов, неспособности запустить профайлер, а также довольно спорного описания самого языка. О проекте при этом ни слова кроме того, что у вас получилось на Go лучше чем на Java.


                        1. softaria
                          31.07.2016 09:01

                          Вы хотите от меня доказательств заведомо ложного тезиса вида «На java нельзя создать такой же быстрй сервер, как на go». Можно. Я думаю, он даже будет поддерживать несколько бОльшее количество клиентов.
                          Я утверждал лишь, что создание такого сервера на go занимает меньше времени и сил.
                          Как наличие (плохого) кода на java и хорошего на go может подтвердить или опровергнуть моё утверждение?


                          1. Randl
                            31.07.2016 11:05
                            +2

                            Я утверждал лишь, что создание такого сервера на go занимает меньше времени и сил.

                            Есть разница между "на Go разрабатывать проще и быстрее, чем на Java, благодаря дизайну языка" и "на Go разрабатывать проще и быстрее, чем на Java, потому что я плохо знаю Java". Вы демонстрируете именно второй случай, а он мало кому интересен.


                            Как наличие (плохого) кода на java и хорошего на go может подтвердить или опровергнуть моё утверждение?

                            Наличие (хорошего) кода на обоих языках подтвердило бы, что речь именно о языках, а не о ваших способностях.


                            1. softaria
                              31.07.2016 14:08

                              на Go разрабатывать проще и быстрее, чем на Java, потому что я плохо знаю Java


                              А go не знаю совсем. Это не меняет дело?

                              Наличие (хорошего) кода на обоих языках подтвердило бы, что речь именно о языках, а не о ваших способностях.


                              Но у меня нет хорошего кода на ява, который делает то же самое. Он мне не был нужен.


                              1. Randl
                                31.07.2016 14:20
                                +2

                                А go не знаю совсем. Это не меняет дело?

                                Меняет. Превращает посыл статьи в "нубы, перебирайте языки пока вам не повезет состряпать удачную архитектуру на одном из них". Если бы у вас и на Go ничего не вышло, вы пошли бы дальше? И мы читали бы статью «ребята, смотрите, C# гораздо менее требователен к вашему времени и усилиям по крайней мере на некоторых видах задач. Если ваши задачи схожи, то C# стоит попробовать. Возможно, вы получите некоторый profit.»


                                1. softaria
                                  31.07.2016 14:30
                                  -3

                                  Я просто не вижу смысла спорить с вами о своём профессиональном уровне.
                                  По двум причинам. Во-первых, вы уже все для себя решили, а во-вторых меня не интересует профессиональное мнение человека, который родился в тот год, когда я написал свой первый профессиональный код — часть АСУТП для Сургутской ГРЭС.


                                  1. Randl
                                    31.07.2016 14:53

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


                                    1. softaria
                                      31.07.2016 14:59

                                      Это я на случай, что кто-то почитает комменты и согласится с вашим посылом про «нубы, перебирайте языки...» только потому, что я ничего не возразил.


                                  1. solver
                                    31.07.2016 15:33
                                    +6

                                    О, пошел в ход возраст. Это много говорит о вас.

                                    P.S. Это случайно не та самая ГРЭС где 2 раза крупные аварии были? Совпадение? ))


                      1. solver
                        30.07.2016 22:19
                        +3

                        > Допустим я скажу, что аналогичная задача на яве заняла у меня X дней, а на go — Y (где Y<X), вас это убедит?

                        Вы вообще не понимаете, что такое «объективность» чтоли?

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

                        Менее требователен по сравнению с чем? Как сравнивали, чем мерили и т.д.
                        Эта фраза и есть «досужие домыслы».
                        Вы даже поправляя «позиционирование» статьи, лучше не делаете. Даже в этих каментах вы не понимаете, что делаете и продолжаете разжигать холивар на ровном месте.


    1. Suvitruf
      30.07.2016 11:07
      +1

      Если честно, я долго пытался понять, шутка это или нет (я про статью). У нас многие игровые сервисы на Java в связке с netty. Оно у меня без особых проблем тысячи коннектов держит.


      1. softaria
        30.07.2016 11:13
        +1

        Видимо я нечетко расставил акценты — очень много одинаковых комментариев.

        Шутка не в том, что java будто бы медленнее. Шутка в том, что решение моей задачи занимает у программиста go намного меньше времени.


        1. Optik
          30.07.2016 11:27
          +4

          С учетом того, что большинство по рассказу выявило в вас профана в java, то да, это конечно очень объективно.


        1. ShadowsMind
          30.07.2016 11:37
          +4

          Откройте для себя Akka (она кстати поверх Netty работает), там создать сервер слушающий TCP/UDP/Web-soket'ы — это дело пары минут. Там вам и прозрачная модель работы с многопоточнотью, и обсолютно никаких блокировок, и поддержка кластера «из коробки» и еще куча плюшек.
          Мне лично Go тоже нравится, игрался с ними недельку после рекомендации знакомого, но для себя не нашел не одного плюса относительно тех задач, которые мне приходится реализовывать на Java, темболее последний год с небольшим работаю со Scala — тут даже сравнивать бесмысленно.


          1. softaria
            30.07.2016 11:50
            -2

            Akka, как и Play — реально хорошие вещи.
            Но у меня стояла другая задача. Я хотел проверить гипотезу о том, что на go решение этой задачи потребует меньше усилий, чем на java.
            Зачем мне это надо? Потому что мне, как владельцу IT компании, важно не пропустить технологическую волну. Не оставить свою команду работать с устаревшими, неэффективными технологиями и не уступить рынок другим, более шустрым игрокам.
            За последние 14 лет ни один из новых языков не дал существенного прироста в производительности. Go оказался первым.


            1. asd111
              30.07.2016 18:00
              +1

              Добрый день. На мой взгляд для вашей задачи так же хорошо подошел бы Erlang. Вы рассматривали Erlang?


              1. softaria
                30.07.2016 18:01
                -1

                Рассматривал. Но мой мозг отказывается писать на нём сколько-нибудь большой объём кода.
                Хотя его концепции мне понравились.


          1. solver
            30.07.2016 15:33

            > Akka (она кстати поверх Netty работает)
            Чушь полная. По верх Netty работают как раз примеры которые привел автор: VertX и Play.
            Что лишь в очередной раз показывает в нем профана в Java мире.
            В Akka же по верх Netty работает только кластер. Т.е. обмен данными между нодами.
            И то это выпилят постепенно. Т.к. в Akka уже есть своя отличная реализация сокетов, модуль Akka.io.


            1. ShadowsMind
              30.07.2016 18:17

              Да, в курсе того, что Netty как депенденси только в remote (а cluster в свою очередь от remote зависит). И про то, что они постепенно от нее избавятся тоже слышал (толи в gitter'е, толи на одной из конференций кто-то упоминал). Просто хотел упомянуть этот факт, надо было сразу уточнить.
              Кстати, а разве Play в свою очередь не делает потуги в сторону того, чтобы полностью заменить Netty на Akka? По крайней мере где-то упоминалось, что они планируют, если я не ошибаюсь.


              1. vadim_shb
                30.07.2016 20:15

                Команда Play пробуют akka-http. Но так как Akka-http еще experimental, и с производительностью там еще не так все гладко, видимо попоробовав — поймут, стоит ли выпиливать netty.


  1. Yeggor
    30.07.2016 13:01
    -4

    Спасибо, интересная статья!


  1. vintage
    30.07.2016 13:30
    +9

    Если без чего-то можно обойтись, без этого нужно обойтись.

    То есть обеспечение безопасности конкурентного доступа на уровне типов — лишняя возможность, а форматировние на уровне языка — жизненно необходимо?


    Код на go на 20-30 процентов короче аналогичного на яве

    А обработка ошибок приводит к большому количеству однотипного кода.

    Взаимоисключающие параграфы.


    Достаточно, чтобы у сущности просто были все нужные методы.

    Это называется "структурная типизация".


    Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом

    Это называется "сопрограмма". Везде реализуется на уровне библиотек.


    Канал в go это очередь (буфер) в один конец которого можно писать, а из другого читать.

    Это называется "блокирующая очередь". Везде реализуется на уровне библиотек.


    можно указать как локальное имя, так и адрес пакета в любой современной системе контроля версий (например, в git)

    Bazaar поддерживается? Svn?


    В go пошли дальше и сделали поддержку управления зависимостями на уровне самого языка.

    Для решения этой проблемы используются внешние инструменты — менеджеры пакетов.

    Без такой неполноценной поддержки тоже было не обойтись?


    1. Sirikid
      30.07.2016 14:24
      +1

      > Везде реализуется на уровне библиотек.
      Постойте, это же параметризированный тип, а их у нас нету, только встроенные :)


      1. vintage
        30.07.2016 20:45

        Имелось ввиду везде, кроме го. :-)


  1. 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. Это важная информация в контексте вашего постоянного уточнения.


    1. softaria
      30.07.2016 17:55

      Как бы вы отнеслись к статье, которая бы начиналась рассказом об авторе его опыте и личных достижениях?
      Думаю, большинство комментаторов уместно поинтересовались бы — чего это автор тут пиарится, вместо того, чтобы говорить дело.

      Смысл статьи коротко можно выразить так — «Люди, смотрите, есть такие задачи, которые на go получается решать намного быстрее, приятнее и эффективнее, чем на java. Будет свободное время — гляньте сами. Время окупится.»

      Проект был всего лишь иллюстрацией. Но если вы, или кто-то другой действительно интересуетесь этим проектом, я отпишу тут подробнее.


      1. webkumo
        31.07.2016 20:27
        +1

        Как можно интересовать тем, чего нет? Вы так и не сформировали чёткой иллюстрации/описания вашего проекта. Поэтому сейчас он не может быть интересен сам по себе. А вот как источник дополнительной информации, которая поможет дать оценку «а стоит ли верить автору» — очень даже.
        Пока что никаких доказательств ваших слов никто не увидел. Вопрос доверия — так же решается не в вашу пользу (у вас нет «кредита доверия» — вас никто не знает).


        1. softaria
          31.07.2016 20:31
          -1

          Вы так и не сформировали чёткой иллюстрации/описания вашего проекта.


          Потому что статья была не о проекте.

          Пока что никаких доказательств ваших слов никто не увидел.


          Что бы вы посчитали доказательством моих слов?

          у вас нет «кредита доверия» — вас никто не знает


          Да, это так. Это было частью эксперимента. Мне нужен был честный фидбэк на статью, а не на статью, которую написал «авторитетный чувак».
          Я его получил. Теперь я лучше понимаю как надо и как не надо писать статьи на Хабр.
          Полезный опыт.


  1. Idot
    30.07.2016 14:12
    +5

    Принцип простоты звучит так:
    Если без чего-то можно обойтись, без этого нужно обойтись.

    Это как? Это как в C++ нет ни Юникода, ни нормальной работы со строками? Или что под этим подразумевается?


  1. OpieOP
    30.07.2016 17:45
    +2

    «Go можно выучить за 2 вечера» стоит отметить, что это это сильно зависит от предыдущего опыта. У меня как у быдлокодера с основным опытом на node.js подробное изучение языка заняло больше времени, т.к. появляется куча новых понятий.


  1. CodeViking
    30.07.2016 17:45
    -1

    Очень интересная статья, язык Go определённо стоит как минимум внимания. Благодарю за материал.


  1. Gitkan
    30.07.2016 17:45

    > После работы с профилировщиками эта цифра выросла до 2500.
    А как получена эта цифра?


    1. softaria
      30.07.2016 17:47

      Путем запуска нагрузочных тестов и измерения используемых ресурсов сервера.
      Дополнительно запускался и «нормальный» клиент для субъективной оценки поведения игры под этой нагрузкой.


  1. KriegeR
    30.07.2016 18:26

    Напишите, как Вы шутер делали. Было бы интересно почитать.


    1. softaria
      30.07.2016 19:13
      +1

      Ну это только после релиза.


  1. doom369
    30.07.2016 20:01
    +13

    Хех. А у меня сервер на java держит 10к клиентов на одном виртуальном ядре за 5$ на DigitalOcean. Давайте все на яву назад переходите :).


  1. antonpv
    31.07.2016 09:10

    Я не понял, а где циферки-графики, как было «плохо» на java и как «хорошо» стало на go? Было 20, стало 2500 — весьма размыто…
    У Вас, батенька, что-то с архитектурой не так, а не у java проблемы.


  1. quwy
    31.07.2016 14:08
    -2

    >На одном сервере можно было запустить не более 300 клиентов.
    И после этого они будут говорить, что Java не тормозит.


    1. softaria
      31.07.2016 14:11

      Java не тормозит. Тормозил мой неоптимальный код и неверно выбранная серверная библиотека.
      Обычно в таких случаях берутся (неудобные) инструменты (VisualVM, например), слабые места изучаются и оптимизируется.
      Но в этот раз мне попалась статья об аналогичных инструментах в Go.
      Мне показалось, что инструменты настолько превосходят java аналоги, что результат будет достигнут намного быстрее.
      Так оно и получилось.


  1. izloy1
    31.07.2016 14:11
    -4

    «на одном виртуальном ядре за 5$ на DigitalOcean» серверок на java генерит ответ минимально за 85 ?s, на Go та же функциональность — 9 ?s.
    Даже «простые» единичные запросы к БД на Go быстрее в 2-3 раза, по сравнению с java


    1. softaria
      31.07.2016 14:12
      +1

      Есть масса обратных примеров.
      Статья не о скорости языка, а о скрости разработки на языке.


    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, то делайте это нормально. А то одолели уже эти околохоливаные посты/комменты гоферов и постоянный наброс на вентилятор.


      1. ShadowsMind
        31.07.2016 22:20
        -1

        Забыл упомянуть: БД — PostgreSQL. Обычный JDBC драйвер(есть просто postgresql-async, возможно он быстрее), для пула коннектов — HikariCP. Никаких доп флагов для JVM не выставлял.


  1. 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к, иначе падает с «кончились ресурсы»). Если же впилить в го — оно встанет раком. Может я просто не так писал слипы в го?


    1. 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


      1. firsttimecxx
        31.07.2016 21:56

        Т.е. я не могу просто что-то запустить в мейн-потоке? Почему? Какие для этого есть причины?

        По поводу вашего кода — вайл там не столько для ожидания завершения, сколько эмуляции нагрузки на основной поток.


        1. 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()
          


          1. firsttimecxx
            31.07.2016 22:44

            Можно.

            но для равноправия потоков заменить

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

            Именно ваш с миллионом горутин

            Какие-то невероятные результаты. Скорее всего там 100к горутин.

            С миллионом горутин и паузами (*)

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


            1. 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/


              1. firsttimecxx
                01.08.2016 01:40
                +1

                Первые два примера только ваш код (во втором случае разве что n увеличено в 10 раз). Никаких больше правок.

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

                У вас C++ сидел в ядре (обрабатывая 100500 потоков)

                Ну он не только в ядре сидел. Он сидел 100500 раз в ядре и 100500 раз в юзерпейсе.

                При этом Go съел чуть больше проца, но и завершился чуть быстрее.

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


                1. AterCattus
                  01.08.2016 15:22

                  >оно не завершается пока все горутины не завершены, даже если я их не жду, что странно.
                  Какие-то горутины не могут получить управление, чтобы отработать, потому цикл ожидания никогда и не завершается.
                  Добавьте runtime.Gosched(), как вам уже советовали.

                  > а что-то посерьёзней, то быстрее они уже не завершатся
                  Как бы разница в пользу Go не стала выше из-за отсутствия переключений ядра и юзерспейса.


                  1. firsttimecxx
                    01.08.2016 19:29
                    +3

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

                    Ещё раз. Меня не интересует как сделать так, чтобы это работало. Меня интересует то — по какой причине это не работает так, как написал я.

                    Добавьте runtime.Gosched(), как вам уже советовали.

                    Это не ответ. Вопрос был не в этом. Повторю в третий раз — почему оно не работает так, как написал я. Какие предпосылки к этому есть, кроме дыры в дизайне.

                    Как бы разница в пользу Go не стала выше из-за отсутствия переключений ядра и юзерспейса.

                    Опять же ни на чём не обоснованные утверждения. На основании чего там станет переключений больше? Потому что кто-то сказал?

                    Ну и для справки — переключение ничего не стоит. Особенно на фоне всплывших подробностей работы горутин с сисколами. Как будет время — я напишу бенчмарки с сисколами и добью эту тему. Другой оратор уже поплыл — до подробностей кричал «горутины аналог мультиплексинга», а после уже «надо юзать горутины с епулом, который собственно их аналогом и является. Бывает.


                    1. Falstaff
                      01.08.2016 19:47

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

                      Не «надо юзать», а «библиотека Go под капотом юзает». Это и есть мультиплексинг. А вообще, firsttimecxx, завязывайте с таким тоном. Вам тут никто ничего не обязан, в том числе по десять раз объяснять всё, что все остальные давно уже поняли или с самого начала знали. Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop? Не знаете, как работают async/await? Бывает. Жизнь — процесс познания нового. Только хамить не надо.


                      1. firsttimecxx
                        01.08.2016 21:28
                        +2

                        Не «надо юзать», а «библиотека Go под капотом юзает». Это и есть мультиплексинг.

                        Это не ответ. Ещё раз, меня никаким тоном пугать не надо. Меня это мало волнует.

                        Хорошо, раскатывать — так раскатывать.

                        Утверждение раз:
                        Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей.


                        Суть — противопоставление мультиплексинга(libevent) и горутин.

                        Утверждение два:
                        Там, где в го используются горутины, в C вы обычно используете libevent а не потоки.


                        Противопоставление горутин и мультиплексинга — два.

                        Далее, когда оратор был зажат в угол — последовало:

                        Но вы можете сделать иначе — вы можете использовать событийную модель. Горутина может вызвать собственную сетевую библиотеку, а та, обёртывая системные вызовы, добавляет сокет в список ожидания epoll(). При этом заблокируется только один поток на все сокеты.


                        Опустим событийную модель — она тут не при делах и я не буду это разоблать, что epoll не про событийную модель, но это такое.

                        Чтобы оратор опять не поплыл с моделью использования горутин — уточним:

                        Миллион одновременных клиентских соединений? Это чуть ли не канонический use case. Живут, что-то считают, засыпают на ввод-вывод, снова просыпаются, умирают.


                        Суть — поток данных клиент/сервер находится в своём потоке(выполнения). Это юзкейс для горутин, что собственно выше я и писал.

                        Далее, мультиплексинг — это про сбор множества потоков данных в один поток, который обрабатывает уже один поток(выполнения) и нет смысла использовать для этого множество потоков(выполнения).

                        Что мы имеем. Оратор, утверждая изначально о назначении горутин как об альтернативе мультиплексинга, т.е. не много потоков(данных) в один поток данных в один поток обработки, а в множество поток данных в множество потоков(исполнения) вдруг переобулся и начал утверждать обратное. Типичное натягивание совы на глобус и подбивание всего под себя.

                        Далее пошла типичная тактика обвинять меня в том, что я чего-то не понимаю и он видите ли мне что-то объясняет, а я не понимаю.

                        Такую же тактику использует адепт ниже, только он на вопрос «почему не работает?» — отвечает «вставьте кастыль — заработает», и каждый раз утверждает, что он отвечает.

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

                        Жизнь — процесс познания нового. Только хамить не надо.

                        Просто смешно. Может мне спросить основание для обвинения меня в " Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop?"? И будет очередное «поплыл»?

                        Ну и конечно же хамить. Это любимое занятие слабой аудитории — сливаться на «хамить» и прочее. А на вопрос «где я хамил» — обвинитель ничего показать не может, а если и может, то связать цитату и «хамил» логически не может.

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


                        1. Falstaff
                          01.08.2016 21:39
                          -2

                          «Тактика», «адепт», «раскатывать»… в странном мире вы живёте. Извините, но еда — всё. Спасибо за диалог.


                          1. firsttimecxx
                            01.08.2016 22:09
                            +2

                            «Тактика», «адепт», «раскатывать»… в странном мире вы живёте.

                            Я живу в этом мире. Не я сливаюсь, не я веду себя так. Не моя тактика основа на вранье, обвинения, уличениях и прочем непотребстве.

                            Люблю эту адиторию. Много из себя строит, а после первых трудностей сбегает.

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

                            Но иногда бывает так, что тот кто спрашивает — спрашивает это не для того, чтобы ему объяснили. А для того, чтобы адепт на кураже выложил все свои представления о теме. А далее эти представления очень просто разбиваются.

                            Ну и да, играть в игру «я не говорил, я не я» с более сильным не имеет смысла, ибо в любом случае разоблачат. Такие дела.


                    1. AterCattus
                      01.08.2016 19:51
                      +2

                      по какой причине это не работает так, как написал я.
                      почему оно не работает так, как написал я

                      Если вы на 4х ядрах без вытесняющей многозадачности запустите 4 cpu-bound потока, а потом захотите запустить 5ый, но он не будет выполняться, — это тоже дыра в дизайне? Больше похоже на неправильное использование.

                      Вы ставите задачи шедулеру, но не даете ему работать. Вам это уже писали.

                      На основании чего там станет переключений больше

                      Потому что нет постоянных переключений огромной кучи потоков. Каждый поток (а их мало, единицы) имеет свою очередь горутин на выполнение, и просто их выполняет по очереди, не покидая юзерспейс.

                      P.S. Если так хочется посравнивать, можете сделать просто два распараллеленных cpu-bound теста рассчетов на хотя бы 10к горутин и 10к потоков. Какой быстрее посчитает и сколько ресурсов съест. Всякие -O2 и -O3 оптимизации для кода на плюсах использовать будет не спортивно, для схожести машинного кода.


                      1. 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 — это не отсутствие оптимизаций, а наличии пессимизаций из-за волатайла.

                        Но это ладно — я сделаю честно.


                        1. iqiaqqivik
                          02.08.2016 07:41
                          +3

                          Вообще про «не включать `-ON` — самый смешной пассаж. Почему вдруг при соревновании в беге двух сущностей я должен своей отрубить ногу?


                          1. firsttimecxx
                            02.08.2016 08:11

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

                            Для того, чтобы это избежать — надо сравнивать реализации не друг с другом, а с деградацией в сравнении с запуском 10к раз на одном(ncpu) тредах.


                            1. iqiaqqivik
                              02.08.2016 09:46
                              +1

                              А, точно, да, спасибо.

                              Поверхностно прочитал.


    1. Falstaff
      31.07.2016 18:12

      Может я просто не так писал слипы в го?

      Скорее всего вы попались на такой нюанс: если вы добавите в ваши процедуры Sleep(), но после их запуска будете непрерывно, в цикле, проверять атомарную переменную (как у вас в примере), то этот цикл просто не отдаст управление гопроцедурам. Не забудьте, что ими управляет не планировщик ОС, а потому надо дать возможность этому планировщику запуститься — главный поток должен заблокироваться хоть ненадолго. В вашем примере проще всего вставить очень маленький Sleep() в цикл проверки переменной.


      Вообще, вы по сути проверили скорость создания потоков. Создание потоков в Linux это быстрая штука, спору нет. Но вы же сами написали, что при равном количестве потоков/процедур у вас пример на C++ вылетает с нехваткой ресурсов. Потоки куда тяжеловеснее по стеку (по умолчанию, если память не изменяет, там два мегабайта), у горутин — два килобайта. Вставьте задержку и посмотрите на maximum resident size, я думаю, что код на C++ покажет гораздо больший расход памяти.


      1. 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к тредов.

        И опять же, как я говорил — гц в реальном приложении на го сожрёт куда больше.


        1. AterCattus
          31.07.2016 22:23

          любая горутина может спокойно покараптить стек другой горутины

          Через unsafe можно, если почти специально. На то он и unsafe. В обычной жизни нет (не рассматриваем ситуацию сейчас с багом самого го рантайма).


          1. firsttimecxx
            31.07.2016 22:37

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


            1. Falstaff
              31.07.2016 23:05

              Реализуется проверкой в прологах функций (оверхед там небольшой). Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется. Здесь оверхед, да, ощутимый, но иначе никак. (Простите, что не с свой разговор влез.)


              1. firsttimecxx
                01.08.2016 02:25
                +1

                Реализуется проверкой в прологах функций (оверхед там небольшой).

                Ну хотя да, если там нету vla и прочих историй, то длину стека функции может почитать компилятор.

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

                Но ведь суть всей ассинхронки именно во внешних операциях. Прочитать сеть, записать на диск, вызвать бдешку и прочее, а всё это си. Каким образом это работает?

                (Простите, что не с свой разговор влез.)

                Это общий разговор.


                1. Falstaff
                  01.08.2016 02:38

                  Каким образом это работает?

                  Мы говорим о вызове функций из нативных библиотек, или уже об асинхронном вводе/выводе? Если горутина делает блокирующий системный вызов, то поток, в контексте которого она выполняется, будет заблокирован этим вызовом, а остальные горутины уйдут в очереди других потоков.


                  1. firsttimecxx
                    01.08.2016 02:50

                    Мы говорим о вызове функций из нативных библиотек, или уже об асинхронном вводе/выводе?

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

                    Если горутина делает блокирующий системный вызов

                    Я говорю про это:
                    Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется.


                    Хотя на блокирующих вызовах это крах всей логики горутин, ибо оно будет плодить потоки системные + смена стека, а на вызовах не блокирующих.

                    Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные, либо внешние, но опять же — через всё это системное ipc, либо сеть, либо файлы.


                    1. Falstaff
                      01.08.2016 03:39

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

                      В Go очень много обёрток и собственных реализаций, в том числе для того, чтобы отвязать горутины от блокирующих системных вызовов. И отсюда же очень малое количество зависимостей у бинарников.


                      Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные...

                      Я опять обращусь к примеру. (Сразу скажу, конкретной реализации именно этой части в Go не знаю, так что пример умозрительный, но кажется, что так и реализовано.) У вас есть несколько горутин, ожидающих ввода/вывода на сокетах. Вы можете сделать несколько потоков и каждый будет ждать ввода вывода, каждый будет иметь горутину в контексте исполнения. Но вы можете сделать иначе — вы можете использовать событийную модель. Горутина может вызвать собственную сетевую библиотеку, а та, обёртывая системные вызовы, добавляет сокет в список ожидания epoll(). При этом заблокируется только один поток на все сокеты. Как только epoll() просигналит, что на каком-то сокете доступен результат ввода-вывода, то это событие поступит в очередь событий, а планировщик даст зелёный свет на выполнение той горутине, которая ждала этой операции. Ради таких вещей горутины и задумывались.


                    1. AterCattus
                      01.08.2016 13:48

                      Ну так Go и не использует libc (или что там идет заменой на других платформах, типа той же винды). Прямые сисколы, а вызов именно сишного кода только для явного вызова сишного кода, а не i/o и прочего.


        1. 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. системные треды» — довольно бесполезное времяпрепровождение. :)


          1. 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. системные треды» — довольно бесполезное времяпрепровождение. :)

            Да нет, это просто отмазки для избежания неудобной ситуации перед простым фактом — горутины не быстрее.

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

            Были бы это не потоки, если бы все эти цепочки горутина->канал->горутина объединялись бы в цепочку калбеков в рамках одного потока.


            1. 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? Это ошибочное впечатление. Я просто пытаюсь объяснить, как всё это работает. Если я вас раздражаю, вы скажите, и я перестану.


            1. SirEdvin
              02.08.2016 13:11
              -3

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


  1. iqiaqqivik
    02.08.2016 17:27
    +1

    Вот только сегодня как раз вышла прекрасная заметка Адама Левенталя; положу тут, за компанию: http://dtrace.org/blogs/ahl/2016/08/02/i-love-go-i-hate-go/