14 июня 2012 в 11:58

C10k (Проблема 10000 соединений) на разных языках/платформах



UPD. Вторая версия бенчмарка тут: eric.themoritzfamily.com/websocket-demo-results-v2.html


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

Подробнее о проблеме 10000 соединений: ru.wikipedia.org/wiki/Проблема_10000_соединений

Как с проблемой 10000 соединений через вебсокеты справятся Erlang, Go, Haskell (Snap), Java (Webbit), Node.js (websocket) и Python (ws4py)?



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

Реализация Время на подсоединение (среднее) Задержка (средняя) Сообщений Соединений Таймаутов соединения
Erlang 865ms 17ms 2849294 10000 0
Haskell (Snap) 168ms 227ms 1187413 4996 108
Java (Webbit) 567ms 835ms 1028390 4637 157
Go 284ms 18503ms 2398180 9775 225
Node.js (websocket) 768ms 42580ms 1170847 5701 4299
Python (ws4py) 1561ms 34889ms 1052996 4792 5208


Реализации на Питоне и Node.js падали на примерно половине соединений.

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

Java Webbit была темной лошадкой, но в итоге показала результаты лучше, чем Go (157 необработанных подсоединений).

Самое удивительное, что gevent (Python) и node.js перестали работать после 5001 и 4792 соединений соответсвенно, несмотря на то, что и тот и другой были реализованы специально для решения проблемы C10k.

Более детальное описание, код и сырые данные — на GitHub'е: github.com/ericmoritz/wsdemo/blob/master/results.md

UPD. В сравнения включается все больше и больше людей, появились тесты для Tornado (Python)



UPD. Вторая версия бенчмарка тут: eric.themoritzfamily.com/websocket-demo-results-v2.html

Dmitrii 'Mamut' Dimandt @dmitriid
карма
–1,0
рейтинг 0,0
Пользователь
Похожие публикации
Самое читаемое Разработка

Комментарии (258)

  • +9
    Тег порадовал «смешались в кучу кони люди». Коль таки дела, спрошу и я. Вот на винде, я понимаю, в WinAPI функция мультиплексирования select — не масштабируемая, и на прикладном уровне дает сложность o(n), что в принципе может создавать проблемы для 10 000 и больше соединений (или все-же справляется?), ну а у linux в чём беда?
    • +2
      Я так понимаю, проблема не столько ОСи, сколько самих веб-серверов, которые могут просто не уметь обрабатывать такое количество соединений :)
      • +1
        Не совсем верно. Например в Java NIO базируется на разных технологиях в разных ОС и соответственно по разному себя ведет.
      • +3
        Название должно быть «проблема 10000 WebSocket соединений», судя по исходникам.
    • +4
      Кто-то ещё пользуется селектом на винде? IOCP же.
      • +1
        Я пользуюсь, но судя по всему, больше не буду.
        • 0
          Посмотрите в сторону htts://github.com/joyent/libuv :)
          • 0
            Что это? И зачем мне на него смотреть? :)
            • +1
              Библиотека асинхронного ввода и вывода, сочинённая специально для внедрения в Node.js.
      • +1
        Кто-то еще пользуется виндой как серверной платформой?
        • 0
          news.netcraft.com/archives/2012/06/06/june-2012-web-server-survey.html

          Платформа как платформа
        • 0
          не знаю к счастью или к сожалению, но у нас в конторе так исторически сложилось, что всё на MS. Я бы рад предложить перейти местами на nix (почтовик бесплатный на iredmail и прокся очень вписываются), но как только с шефом начинаем обсуждать, видим что пока проблем больше чем плюсов…
          Так что коли вся сетка на Win, выбирать особенно не приходится… Хотя может время изменится для нас =)
    • +3
      Select никто и не использует. На винде есть IOCP, на линуксе epoll, на FreeBSD и ее производных — kqueue. Это если рассматривать уровень системных вызовов.
      • +1
        и есть несколько различных либ, скрывающих детали конкретной ОС.
        • +3
          например, сказочный boost.asio для с++. С приходом лямбд он стал очень удобным.
      • +5
        Если не требуется адового количества соединений, то можно и select.
      • +3
        Та ладно! Половина open source софта, весьма известных названий с которым я имел дело, вообще не знает каким именно чудом оно компилируется под винду. IOCP для них — черная магия. Пишут в лоб да как по-проще. И это еще в лучшем случае.
    • 0
      Под вынью не пробовал, но поговаривают 10к не тянет.
    • +4
      Вот на винде, я понимаю, в WinAPI функция мультиплексирования select — не масштабируемая, и на прикладном уровне дает сложность o(n), что в принципе может создавать проблемы для 10 000 и больше соединений (или все-же справляется?), ну а у linux в чём беда?


      При всем моем уважении, select() была функцией мультиплексирования на винде лет двадцать назад. Последние лет… много используется GetQueuedCompletionStatus() которая волне себе способна держать до миллиона входящих TCP подключений, из них одновременно передающих данные ~ 10k.
      • 0
        Ну, наверное я немножко устарел. Года 2 назад писал веб-сервер, не помню что курил и читал, но альтернативы тогда не нашел. Сейчас сеть у меня сводится к QNetworkAccessManager, как бы печально это не звучало.
        • +4
          При всем моем уважении и любви к Qt, QNetworkAccessManager не предназначен для создания чего-нибудь сложнее нескольких соединений. По этому поводу есть много материалов в гугле, но если есть желание можете посмотреть в код — он там простой и страшный.
          • +1
            Для винды он там cводиться к WaitForОлолоОbjectОлоло, смотрел. Да знаю я, просто как факт, там где нужна высокая производительность, я так и не делаю, а Qt для клиентский приложений — awesome.
    • +2
      А при чем здесь винда? Это select сам по себе такой. Более того, оригинально он еще и битмаски использовал, что мешало ему работать с дескрипторами имеющими номер выше определенного (насколько я знаю apache делает кучу dup2 для перемещения несокетных дескрипторов «вверх» и сокетных — «вниз»). Вообще, история c10k в юниксах (включая wannabe — типа линукса) — это леденящий душу триллер.
  • 0
    А почему ожидалось, что Go порвет Erlang?
    • 0
      Нативно-компилируемы потому что, наверное
      • +3
        А при тестировании Erlang использовался HIPE или нет?

        Еще, я смотрю есть код для Ruby, как он себя показал?
        • 0
          Честно не знаю :)
  • +3
    Во-первых, «C10k», почти наверняка, — проблема 10 тысяч соединений, а не тысячи.
    Интересней было бы добавить сюда реализацию на каком-нибудь С (или хотя бы с использованием либы на С). Так, чисто для сравнения. Ну и перл с haskell'ом, чтоли.
    • 0
      Да, уже исправил на 10 000 :)

      Хаскель в бенчмарке есть, а С и Перл можно добавить (Гитхаб же :) )
      • 0
        да, хаскел «не заметил»: задумался на середине ответа и дописал хаскелл уже позже ;)
        Пойду попробую изобразить что-нибудь на перле аналогичное…
      • 0
        Я исходники не смотрел, но судя по описанию действительно тест 1000 подключений происходит, так как при создании подлючения каждую миллисекунду = 10 секунд по 1000 подключений в секунду.
  • +8
    s/Латентность/Задержка/
    • +1
      Ох уж эта политкорректность! :) Сейчас исправлю :)
  • 0
    довольно интересно. обязательно попробую у себя на сервере.
    какая версия nodejs у вас использовалась?
    • –1
      Что говорится, мопед не мой, так что не знаю :)
      • +2
        Стоп, а если мопед не ваш, то где ссылка на автора? Я до последнего комментария был уверен, что это ваше исследование и вы провели позитивную работу и сделали вклад. Черт побери!
        • –2
          :) Ссылка на автора — ссылка на Гитхаб :)
    • 0
  • 0
    С Go в этом случае причина, насколько я понимаю, состоит в том, что по умолчанию «goroutine», которые используются в Go для реализации многопоточности, являются легковесными только до тех пор, пока им не понадобится делать какие-нибудь блокирующие операции, например чтение-запись в сокеты. Когда же goroutine требуется прочитать что-то из сокета, она превращается в обычный thread операционной системы, что должно весьма плохо сказываться на производительности, хотя коннект может действительно при этом идти быстро.
    • +2
      Все операции ввода-вывода и прочие системные вызовы в Go асинхронны хоть и имееют api который выглядит, как блокирующий. Единственный способ написать блокирующий код в Go — это долгие вычесления, которые обычно достаточно быстры благодаря компилируемой природе языка.
    • +1
      Кроме того горотуны не превращаються в обычные потоки в класическом понимании. Планировщик (scheduler) выполняет их в зависимости от того ждут ли они на результат асинхронной операции (любые системные вызовы или ожидание на ответ из канала), или же готовы к исполнению, на одном из реальных thread-ов, которые есть у него в пуле (на данный момент количесто таких потоков зависит от переменной среды GOMAXPROCS).
      • 0
        Так почему он себя так плохо показал? Выходит го не подходит для высоконагруженных проектов?
        • 0
          Ну конкретно у реализации вебсокетов модель немного другая, насколько я понимаю — они больше заточены под более-менее тяжелую обработку запросов, нежели на замену nginx. Ещё может быть вариант, что автор что-то не так намерял, ибо он, видимо, в 32-битной системе это тестировал.
          • 0
            То есть если поставить перед го приложением nginx то будет всё ок?
            • 0
              Насколько я знаю, на Хабре есть люди, которые используют Go в продакшне, лучше всего у них спрашивать :). Я не вижу особого смысла в nginx ни для этой задачи, ни для каких-либо других. Разве что для раздачи статики лучше nginx использовать, но это обычно итак делается с других IP и доменов.
              • +1
                Был Pirro, он ещё сериал про создание сайта на го запускал. Только пропал он и на лс не отвечает
        • +3
          Попробуйте тот же Go только используя компилятор GCCGO. Обычно это дает ощютимый прирост производительности. На данный момент стандартная связка для Go значительно слабее оптимизирует чем GCC. Это скорей всего улучшиться в будующем, но сейчас удобней разрабатывать с стандартным компилятором, а в продакшн с GCCGO.

          Кроме того библиотеки в Go достаточно свежы и возможно что-то и где-то можно оптимизировать. Если у вас есть идеи/пожелания — посылайте их golang-nuts или golang-dev рассылки и вас скорей всего выслушают, а если будет еще и какие-то изменения, которые очевидно улучшают производительность — с радостью их приймут.

          Наверное самым слабым местом в Go сейчас являеться планировщик, который определенно будет улучшен в будующем (GOMAXPROCS — хак, а не решение всех проблем).
      • 0
        Я, честно говоря, тоже себе примерно так это и представлял, но видимо это не вся правда…
  • 0
    10к это было давно для обычных сокетов, сейчас для той же джавы 10к уже не проблема.

    А веб сокеты что ли только подбираются к этому пределу? Или я что-то не так понял?
  • +2
    а зачем вебсокет… надо было tcp сокет делать
    • +7
      Тоже смотрел на результаты с недоумением. Также для питона не плохо было бы добавить результат по Tornado.
      • 0
        А лучше сразу для gevent
        • –1
          O_o
          А сейчас там что?
          • +2
            Там в ws4py старый gevent, а не 1чка, насколько я помню. 1чка на другой либе с кучой багфиксов и крэшфиксов.
            Более того, насколько видно сравнение некорректно, т.к. процесс не параллелили.
            Пускай запустят например даже gunicorn+gevent, это вполне возможно, с учетом использования wsgi.

            • 0
              gevent 1.0 еще не зарелизили, так что всё честно ^_^ Ну и сомневаюсь, что обновление до 1.0 хоть что-то существенно исправит.

              wsgi в вебсокетах не используется, насколько мне известно.

              Ну и, пожалуй, есть смысл сделать erl -smp disable для эрланга и замерить как эрланг будет себя вести, если отключить расползание по процессорам.
              • +2
                Исправит фундаментальные баги в libevent, который заменили на libev в gevent 1.
                Ну значит тест не честный опять же.
                Надо было переписать ws4py с мультифорком, чтобы у каждого хаба geventа была возможность заполнить все ядра. В эрланге это нативно.

                Я это к чему. Мы держали 20000 соединений TCP постоянных на 2 серверах (по 5 тысяч соединений на сервер + mysql + memcache).
                Если бы не проблема миддлвари можно было бы вешать и больше соединений.
  • 0
    То что NodeJS и Python перестали работать — скорее всего уперлись в ограничения ОС (количество файл-хендлов) надо ОС подтюнить и должны заработать.
    • +1
      По ссылке ходили?
      ulimit -n 999999
    • 0
      NodeJS и Erlang нельзя сравнивать так в лоб.
      В Erlang из коробки многопоточность. В то время как на NodeJS надо поизвращаться.
      Сравнение Erlang и Node.js
      • +3
        Уже есть cluster.
        В данном примере не включен cluster. Поэтому результат неточен.
        • 0
          Так я именно про это и говорю.
  • +1
    Из описания непонятно, как рассчитывалось «Соединений» и с какой точностью. Может там до 10K одновременных далеко еще.

    Кстати, автор там чего-то подрефакторил и будет повторно тестировать. Подождем.
  • +3
    Табличка вообще не имеет смысла, поскольку задача решена только Erlang. Остальные просто выпадают из сравнения, как не решившие задачу. Смысла сравнивать по остальным параметрам нет. Если же идти на компромисс и учитывать только отработанные запросы, то не понятна средняя задержка у NodeJS в 42 секунды — не верю!
    • +3
      По поводу средних 42 секунд (если вы считаете, что это много).

      Вполне объяснимая задержка – нода ковыряется на одном процессореядре (про cluster писали выше ), очередь сообщений копится, node не успевает всё обрабатывать, и поэтому «вжжжиииууу» © получается только на старте.

      Грубо говоря, запустив ещё один node.js на другом ядре можно удвоить скорость, если есть ещё свободные ядра – будет +100500 к скорости такой вот синтетической «обработки» сообщений. На практике цифры конечно не такие радужные, ибо бизнес логика, mongo/mysql + гремучая смесь различных модулей из npm, которые поголовно версии ~0.x / ~0.0.x.

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

      PS: А ещё оно при «правильном» обращении умеет течь, причём всем сразу. Но это уже руки.
  • 0
    Кроме того, актуальность самой проблемы C10K мне кажется преувеличенной. Когда нагрузка вырастает до таких размеров, неизбежно начинается горизонтальное масштабирование по другим причинам. Хотя бы из-за надежности. Причем его можно начать уже с 1K и данной проблемой не париться.

    Или я ошибаюсь?
    • +8
      Это концептуальная проблема. Она ценна не самом по себе, а для оценки системы в целом. В частности — когда именно пора делать горизонтальное масштабирование :).
      • +1
        Так моя мысль и состоит в том, что «пора» наступает намного раньше, чем исчерпываются возможности веб-сервера по обработке соединений. Не хватает CPU, памяти надежности и т.д.
    • +5
      Вебдевелопер?
      Не всё так легко горизонтально масштабировать, есть приложения которые отлично справляются со своей задачей без горизонтального масштабирования и обслуживают по 10тысяч соединений.
      • –1
        Интересны ваши примеры. Я видел разные приложения, но с 10К — нет.
        • 0
          Ну если нужен пример того, что будет проблематично горизонтально масштабировать, то игровой сервер для игрушки типа wow с общим миром на 10к игроков.
          А если просто сервера, обслуживающие 10ки тысяч полуактивных соединений, то это мессенджеры, системы мониторинга итд.
          • +1
            Нужны реальные примеры. Теоретически-то я представляю. А вот в реальности как системы работают, это интересно.

            Например из Яндекса или из другого highload проекта кто-нибудь сказал бы, по сколько соединений у них обслуживают фронт-енд сервера. И как они понимают, что пора добавлять. Сдается мне, что упираются узким местом становится совсем не количество соединений.
            • 0
              UO сервер, далёкий 2003ий год на старом железе и тогда ещё на тормозном .net'е: «During our stress test we had over 9,000 users logged into UOGamers: Hybrid. We were still able to walk, talk and run around despite some small amounts of lag. The server held it's own with over 9,000 users logged in»
              И сетевая часть там достаточно ужасно реализована.
              • +1
                Если я не ошибаюсь, в ультиме, если не стоят посреди города в самой гуще общения с сервером будет очень. Даже очень мало. Помню я где-то в начале 2000-х играл в УО на модеме и всегда обходил стороной центр города, а вроде-бы в где-то в 2004-м, когда в Москве только начал появлятся выделенный интернет (со скоростью чуть большей, примерно в 4-8 раз, нежели модемная) у меня друзья держали свой сервер где по вечерам играли до 500-600-700 человек (точные цифры уже они наверное и сами не помнят).
                • 0
                  Во время стресс теста лаги появились из-за недостаточной пропускной способности канала 1Gbit.
                  • 0
                    А вот это уже интересно. Хотя и немного странно: во временя УО каналы были, мягко говоря, не такими широкими как сейчас. Не представляю себе ситуацию, как 15 лет назад на комманду логина мне могли прислать xml-лину или json-нину в пару тройку метров (как это делают сейчас многие).
                    • 0
                      На время теста была предоставлена дорогая по тем временам железяка и хороший канал. Но сам сервер можно считать что однопоточный, кроме идиотской реализации таймеров/таймаутов которая вынесена в отдельный тред, сохранение мира в несколько тредов, ну и сеть через iocp(tp).
            • +1
              Ну допустим игры в социальных сетях, там несколько десятков тысяч конкрарентов это нормально. То чем занимался я, не было столь успешно и держало всего лишь до 4к на одной ноде (около 1к io бинарных пакетов в секунду), просто больше народу не приходило :(. Загрузка, я бы не сказал что была такая уж и большая, таски выполнялись достаточно быстро. В среднем по мс на таску (типа посадить дерево, собрать урожайчик) — не подскажу уже, но там счет был в миллисекундах.

              Из достаточно популярных социалок, был перед глазами пример как 2 сервера обрабатывали до 27к+ конкарентов (соотношение по серверам примерно 3к1, io-пакетов в секунду примерно 3-4к), к сожалению что там и как дальше было — не в курсе, знаю что серверов стало чуточку больше как и пользователей.

            • +2
              Ещё кое-что вспомнилось по миллиону соединений :)
              www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-3
              blog.whatsapp.com/index.php/2011/09/one-million/
              • 0
                Да, впечатляет.
                Хоть и сделано было в обоих случаях, как я понял, чисто «на рекорд».
            • +3
              У нас («Мамба») сервера, которые обслуживают real-time штуки — соединение по amf-протоколу с флешкой и соединение через long polling/comet — держат порядка миллиона соединений каждый (или, во всяком случае, держали, когда я смотрел это последний раз). линукс, написаны на плюсах, особых проблем не наблюдается.
              • +1
                long polling это немного другой сценарий. Но все равно интересно, спасибо. Сколько памяти используется в среднем на сессию?
        • +2
    • +6
      Представьте, надо Вам обработать 30к соединений.
      Вот и вопрос: либо 4 (+1 для надежности) машины на Erlang, либо 10-20 машин на условом другом языке, который тянет только 1К.
      Есть разница с точки зрения стоимости решения?
      • 0
        Вот я к этому и клоню, к стоимости.

        Если честно, 30К не представляю. :) Но давайте прикинем, теоретически. Сколько нужно памяти на одну сессию? Допустим 300 Кб; тогда на всех нужно 8.5 Гб. Это скромная оценка, при 64-разрядном приложении может и все 16 выйдет. Так же прикинем необходимую мощность CPU, I/O и других подсистем. А дальше прикинем, как выгоднее — распределить все эти пощности на 1-2 сервера или на 10-20? Если на 1-2, то наш выбор ограничивается «большими» серверами от известных вендоров. Их стоимость, стоимость поддержки и особенно стоимость компонентов для апгрейда вы, надеюсь, представляете. В случае же с 10-20 блейдами стоимость в расчете на один мегагерц CPU, гигабайт ОЗУ или гигабайт дискового пространства выйдет намного дешевле.

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

        Так что разница есть.
        • 0
          > Допустим 300 Кб; тогда на всех нужно 8.5 Гб
          nginx: «10,000 inactive HTTP keep-alive connections take about 2.5M memory;»
          • 0
            Это прекрасно, но мы же говорим о системе в целом, а не об одном Nginx.
            • 0
              Ну берём опять же игровой сервер, весь мир хранится в памяти, так что без разницы сколько у нас там соединений, всегда будем отъедать nM памяти. Возьмём опять же ультиму, с жутко переполненым миром и будет у нас ~1G на динамические сущности + ~1G на карту/статику.
              Подключим к этому серверу 10,000 соединений, теперь наш сервер отъедает на 2,5M больше памяти.
              Как от кол-ва соединений может взлететь расход памяти мне не особо понятно.
              Предположим что к нам подключились какие-то мудаки, которые отправляют пакет максимально допустимой длины и висят недоотправив последний байт, мы изначально ограничили максимальный размер пакета в 64K, тогда конечно придётся к этим 10,000 соединениям прибавить ~625M.
              • 0
                > Как от кол-ва соединений может взлететь расход памяти мне не особо понятно.

                Данные самой сессии где-то держать надо?
                • 0
                  typedef struct epoll_handler epoll_handler;
                  struct epoll_handler {
                    int (*fn)(epoll_handler*);
                  };
                  
                  struct session {
                    int fd;
                    int events;
                    epoll_handler handler;
                    list timeouts_node; // intrusive list, 16B на 64бит
                    buf read_buf; // 24B на 64бит +- расход на недогруженые пакеты в пределах 64B
                    queue write_queue; // 16B на 64бит +- расход на пакеты для отправки
                    size_t write_offset;
                    int player_id;
                  }
                  

                  + затраты ОС
                  + активация нескольких таймеров, связаных с залогинеными игроками.
                  От этого расход памяти особо не взлетит.
                  • 0
                    Вы так и не сказали, где держатся данные самой сессии — то есть данные залогиненного пользователя ;) только player_id можно не обойтись
                    • 0
                      Вся информация обо всех игроках уже находится в памяти и не зависит от количества сессий. Когда игрок выходит из игры, то просто переходит в состояние, когда другие его не могут видеть, но данные об этом игроке всё равно важны для нормального функционирования всего мира.
        • +4
          300Кб на одну сессию… в некоторых случаях жировато будет. Хотя в яве допустим 300кб — это смешные цифры, особенно если в хипе куча коллекций (там оверхед до 98% бывает, например ConcurrentHashMap с парой простых объектов из нескольих полей).

          А так, у меня при 1к онлайне и ~1.5к юзеров в памяти (при кэше в виде SoftReference) хип отъедал до 2 гигов. Собственно по метру на пользователя. При использовании кэша с WeekReference цифры были немного другие, при той же тысячи, в хипе около 1.2-1.3 гига.

          • 0
            32 бита?
            • +1
              64, у меня в среднем было 200-300кб памяти на казуала, всякие задроты и топ-левел игроки отъедали примерно по 0.7-2мб.
        • 0
          > Если честно, 30К не представляю. :)
          Все определяется приложением и проектом. У меня сейчас в пиках до 25К.

          > Но давайте прикинем, теоретически. Сколько нужно памяти на одну сессию?
          Это сильно теоретически, все зависит от того, что делать.
          В некоторых задачах на 1 коннект нужно меньше 1КБ.
          Есть даже пример — комет-сервер на Erlang, держащий 1 миллион(!) подклключений. Это на одной машине! Если не путаю, там 64ГБ оперативы. Вобщем не такие страшные цифры на сегодняшний день. Типовая машина.

          > Кроме того, при дальнейшем масштабировании стоимость каждой дополнительной единицы мощности в первом случае будет возрастать, а во втором — оставаться такой же или даже падать.
          Разве я написал, что надо работать на 1 супермашине?
          Ни в коем случае! Приложение должно эксплуатироваться минимум на 2 машинах, чтобы при сбое, оно могло продолжить работу. Даже пример привел: 3 рабочих сервера + 1 запасной.
      • НЛО прилетело и опубликовало эту надпись здесь
    • +2
      1к — это все таки довольно мало. Хотя опять же, смотря для чего. Если взять к примеру геймдев, то 1к юзеров в мморпг на одной машине — много, особенно если они в одном месте. Для тех же социалок, 1к — раз плюнуть. Одной строчкой кода ставим ограничение на клиенте на действие, раз в три-четыре секунды + анимация этого всего и у нас поток запросов снижается в несколько раз (больше чем в три). Тут и 10к нормально живет и вторую машину не требует (если коечно постоянно в рсубд не лезть).
  • +1
    Очень странные результаты. Проверю вечером на сервере.
    • +1
      Пожалуйста, выложите результаты. Очень интересно.
  • +2
    Немного большего ожидал от node.js
    • +2
      www.insight-it.ru/masshtabiruemost/arkhitektura-vkontakte/

      Утверждается, что чат у Вконтакта живет на node.js, на 5 серверах, используя по 4 процесса на сервер, при этом, пиковая нагрузка составляет 150 000 соединений. Итого, 150 000 / (5 * 4) = 7 500. При этом, здесь говорится, что node.js падает, грубо говоря, на 6 000 соединений.

      С другой стороны, Erlang, как и ожидалось (я, как увидел Erlang в списке тестируемых серверов, сразу глянул на автора статьи — и не ошибся), показал себя не просто лучше всех, а единственно правильно. То есть, безупречно. Блин… а ко мне, как раз, с Амазона в понедельник книжка приехала «Erlang programming».
      • +1
        При том что эти сервера ещё и держали коннект с MySQL базой.
        • +1
          Да, кстати, немаловажное замечание: в случае, если данные о Вконтакте верны, там не просто синтетические соединения ради теста, а рабочие…
          • 0
            На момент написания поста данные верные, насколько это известно от разработчика той вресии сервера.
      • 0
        Это судьба.
        • 0
          Мы сами творцы своего счастья. Амазон же не от доброты душевной мне ее прислал ))

          Но, честно сказать, вот так вот, после тесного общения с PHP и JS… Erlang кажется чем-то запредельным. К тому же, не изобилует комплит бегиннерс гайдами. Вот я уже почти неделю штудирую все вдоль и поперек в поисках такого про Webmachine — как создать Restful API с его помощью. А вот для node.js подробный гайд сразу нашелся.
          • +1
            > Вот я уже почти неделю штудирую все вдоль и поперек в поисках такого про Webmachine — как создать Restful API с его помощью.

            Берется wiki.basho.com/Webmachine-Resource.html и потом любой проект с использованием webmachine, и смотрится в код :)

            Ну и добро пожаловать в erlanger.ru/page/672/soobshhestvo (рассылка и чат)
            • 0
              и потом любой проект с использованием webmachine, и смотрится в код
              Я пытался. Я честно пытался. Не поверите — мне потом снился Erlang.
              • +1
                На самом деле главная проблема в том, что webmachine — это HTTP-фреймворк, а не REST-фреймворк. Но в какой-то момент в голове происходит щелчок и становится понятно.

                Спросите в рассылке, может у кого есть простейший пример
                • +2
                  Простейший пример — это ложный путь. Надо отталкиваться не от синтетических примеров, а от примеров работающих приложений.

                  И вот одно такое: github.com/tegioz/wall
                  • 0
                    Ну, можно и так :)
          • +6
            Чтобы понять эрланг, нужно забыть все, что знаете о программировании на императивных языках.
            Мои основные ошибки при изучении:
            1. Пытался использовать эрланг как питон
            2. Считал эрланг высокоуровневым.
            Насчет второго: эрланг примерно столь же низкоуровневый, как и Си. Только он отражает работу совершенно другого процессора.

            Ну, и начинать изучение эрланга с использования webmachine – примерно то же, что начинать изучать Ruby с рельс.
            • +1
              Ну, и начинать изучение эрланга с использования webmachine – примерно то же, что начинать изучать Ruby с рельс.
              Отчасти вы правы, но только отчасти. Я не хочу спорить. Я стал интересоваться им для решения конкретной задачи — организации четко определенного API и пока не более. Да, звучит довольно легкомысленно. Я на раз-два-три могу сбацать такое API, по крайней мере, на node.js. На раз смогу сбацать на PHP. Оба варианта будут в изрядной степени приемлемы (требования определяю я же).

              Это похоже на то, как человека бросают в воду, а дальше два варианта — либо выплывет и научится плавать, либо спасают его.

              Заранее, чтобы не плодить холивары — можете считать, что я так развлекаюсь и полностью отдаю себе отчет о возможных последствиях.
              • +1
                > Это похоже на то, как человека бросают в воду, а дальше два варианта — либо выплывет и научится плавать, либо спасают его.

                Лучший способ учить язык, имхо :) Потому что хеллоуворды действительно неинтересны и ничему не учат
            • +1
              Если Эрланг такой же низкоуровневый как Си, то OCaml — это ассемблер :) У меня, при первом знакомстве с последним было впечатление, что я до этого момента никогда не видел функциональных языков. При том, что стандартную эрланговскую книжку уже прочитал.
      • +3
        > 7 500. При этом, здесь говорится, что node.js падает, грубо говоря, на 6 000 соединений.
        Это числа одного порядка, чуть сильнее проц, чуть другие настройки ОС, немного более сложная обрабтка соединений, и одно превращается в другое. Вот если бы было 6К и 30К — это была бы ощутимая разница.
  • 0
    На Гитхабе отображается интересная статистика используемых языков:

    • +3
      Ну так все логично. Сам тест то на эрланге написан.
  • +4
    Судя по коду node.js работал всего лишь на одном ядре…
    • +2
      В этом, собственно, одна из проблем ноды — то что SMP надо устраивать ручками
      • 0
        Да я то в курсе… Щас просто понабегут нодахейтеры)
      • –3
        Это не проблема ))) А особенность
        • +12
          Для фреймворка, позиционирующего себя как для «building fast, scalable network applications.» отсутсвие smp — это не особенность, а недостаток
          • 0
            Возможно, но сколько времени займет переписать написанный код на эрланге и написанный код на яваскрипте?
            • 0
              Если он уже написан, зачем его переписывать? :)

              Вопроса не понял :)
        • 0
          вы ещё скажите «фича»
      • –4
        С тем же успехом можно сказать, что если надо запустить erlang на одном ядре — это надо устраивать ручками.
        • +4
          Для фреймворка, позиционирующего себя как для «building fast, scalable network applications.» отсутсвие smp — это не особенность, а недостаток
          • +2
            Именно поэтому node cluster уже как полгода доступен. Попробую выжать вечером побольше RPS из этого бенчмарка.

            P.S. Я бы не тратил силы на критику проекта с версией 0.6.19 ;)
            • +2
              Поверьте, это не аргумент. Притом, что я, тем не менее, отношусь с большим уважением к node.js (ну не знаю… я вообще очень позитивный человек и верю в лучшее), но их главная страница, как это и полагается, довольно вызывающа. Типа, посмотрите, поцанчики — нас юзают и Yahoo, и ebay, и Linkedin. Так что отсыл к версии выглядит немного… по-детски, что ли. Как и утверждение «для каждой задачи свои инструменты» в данном контексте.

              Вот аргумент «у node.js все еще впереди» — это уже более весомо. И я, кстати, согласен. Но! Erlang, сволочь, харизматичный. Сначала я напугался. Сильно. Теперь у меня чувство… что-то вроде «вон сколько программеров осилили его, я чо, хуже, что ли».
              • 0
                И ведь действительно используют. И на больших нагрузках. И они смогли написать модуль для кластеризации и довели его до включения в ядро. о том я и говорю, что на данный момент это в Node.js есть и незачем ссылаться на статьи годовалой давности м надежде подкрепить свою убеждённость что node.js чего-то не умеет :) Год назад у них на сайте совсем другой текст бы :)
                • 0
                  Вот что бывает, когда пишешь комментарии на Хабре во время работы :)
            • +2
              Вот кстати, с кластером очень интересный эффект получили.
              Запустили на нем приложение — без нагрузки 2 ядра загружены на 100%.
              • 0
                Они друг за другом следят
      • –1
        Не вижу как можно в ноде что-то выиграть от использования SMP, это же тупо запуск нескольких процессов. С тем же успехом можно и на NUMA гонять, у ерланга в этом плане более выигрышное положение.
        • 0
          Ну и я, в принципе, о том же :)
      • +1
        могу ошибаться, но вроде собственно IO в Erlang работает в отдельном одном потоке. А уже обработчики могут расползаться по ядрам.
        • 0
          I/O которое файловое — да. Насчет сети не знаю. Скорее всего тоже, но именно сетевая часть у Erlang'а быстра и непробиваема :)
  • +1
    Ох, лол. В вики написано, что Tornado успешно преодолевает 10k.
    • 0
      Вики лучше не верить. Вон, node.js как бы тоже должен его преодолевать :)
      Ну и про торнадо относительно старое: lionet.livejournal.com/42016.html
      • 0
        Вы погодите петь победную песню, погодите. Вечером вон товарищи обещали перепроверить данные.
        • +2
          На гитхабе уже накатали тесты для Tornado.
    • +2
      Все зависит от архитектуры, изначально предполагается, что торнадо будет запускаться в несколько апстримов с балансировщиком.

      Производительность отдельного воркера, имхо, достаточно зависимая и непоказательная величина, на которую влияет многое, но в основном количество блокирующих i/o операций в них (например, сделать запись в лог), так как сервер псевдоасинхронный.
      • +2
        Увы, ребята из мира Erlang привыкли что это работает из коробки и встроено в язык/VM. Пожалуй это единственное, что мешает сторонам договориться.
  • +1
    Никому не кажется, что c10k уже основательно устарела? Вот 100k еще актуальна, а для 10k соединений достаточно взять любой удобный хотя бы jit'ируемый язык без сборщика мусора (как известно, эта дрянь обожает стартовать в самые неподходящие моменты), и дело в шляпе.

    P. S. знаю о чем говорю, писал polling сервер, который не напрягаясь обслуживал 30k одновременных соединений в пике.
    • –1
      Да как бы пофиг на каком языке сделать accept 100k соединений, это не проблема. Большинство проблем с обслуживанием 100k соединений появляется от использования всяких libuv.
      • –1
        libuv


        В смысле от библиотек, которые делают веб-разработку удобнее? Это для области «менее 500 запросов в секунду». Проблема c10k/c100k, как правило, либо нивелируется фронтендом, за которым живут десятки бакендов с этими «libuv», либо решается вручную с минимумом фреймворков и элементами тактодрочерства.
        • 0
          >В смысле от библиотек, которые делают веб-разработку удобнее?
          >Проблема c10k/c100k, как правило, либо нивелируется фронтендом, за которым живут десятки бакендов с этими «libuv»
          Ох уж эти веб-разработчики :)

          Ну например Boost Asio делает разработку сетевых приложений удобнее, а вот libuv создаёт проблемы с масштабированием, что можно забыть про сотни тысяч соединений.
          • +1
            А в чем заключаются проблемы libuv кстати?
            • 0
              всё завернули в proactor pattern из-за винды.
              А на юниксах можно использовать reactor pattern и для обслуживания 100к тысяч полуактивных соединений не надо будет аллокэйтить 100к тысяч буфферов.
              • +2
                А не, сейчас глянул исходник, они в отличие от многих других библиотек, которые реализуют работу с сетью в винде/юниксах, пошли по более эффективному решению и сделали alloc_cb параметром read'а вместо готового буффера — это позволяет на юниксах делать этот alloc только когда в сокет что-то прилетело.
                Хотя есть ещё куча претензий вроде отсутствия интерфейсов, которые используют readv, но это уже не так важно. Проблема с масштабированием на юниксах снимается :)
          • +1
            >libuv создаёт проблемы с масштабированием
            а можно поподробнее?
          • +1
            Boost Asio

            Зачем нужна эта громадина, когда есть libev/libevent или epoll/kqueue для любителей все делать своими руками?
    • +5
      В Erlang'е есть сборщик мусора. И?
      • –3
        Возможно, если бы его не было, среднее время соединения было бы значительно меньше секунды.
        • +5
          Ели бы у бабушки был член, то она была бы дедушкой ©

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

          • –1
            имея на руках данные о прекрасной производительности


            Почти секунда на установку соединения как-то не вяжется в моем понимании с «прекрасной производительностью».
            • +2
              Ть вот эта установка соединения почти наверняка к GC не имеет никакого отношения.
  • 0
    Ткните пожалуйста ссылкой на тест с Tornado?
  • +5
    Pythin (ws4py)
    Who is mr. Pythin? :)
    • +2
      Исправил, спасибо
  • +1
    А есть результаты по EventMachine?
    • 0
      Пока нет. Если будут, будут тут: github.com/ericmoritz/wsdemo/blob/master/results.md
      • 0
        А можно их реквестировать в тексте статьи? Не сильно ведь будет страшно поставить второй UPD. Или третий…
        • 0
          если я не забуду и если будет время :)
  • +1
    > Во время бенчмарка каждую миллисекунду запускается новый клиент.
    Вот здесь основной затык. Реально пользователи не будут коннектиться каждую миллисекунду. Если создавать коннекшны с бОльшим интервалом, например втечении пяти-десяти минут, то количество коннекшнов будет гораздо больше.
    • 0
      Синтетические тесты помогают просто оценить и понять порядок вещей. Они не служат более конкретной цели.
      • +1
        Это да, только в данном случае мерялось скорей производительность создания коннекшнов, а не их работы. Создание коннекшна — тяжелая операция как для ОС, так и для платформы. Если создавать коннекшны неспеша, то Java, например, легко может держать и более 10к коннекшнов. Реальная проблема возникает при числе коннекшнов близком 32767.
    • 0
      > Реально пользователи не будут коннектиться каждую миллисекунду.
      Вот тут большой вопрос.
      Представьте, что у вас приложение рестартовало по какой-либо причине. Не важно: сетевой сбой, все клиенты отвалились, вы закрыли критическую уязвимость в коде и его нужно перезапустить и пр.
      В этой ситуации как раз все клиенты будут ломиться одновременно. И может создасться ситуация, что приложение не сможет подняться, т.к. каждый раз будет падать в процессе запуска.
      Итог: приложение может держать все коннекты, если они набираются не слишком быстро, но до первого чиха. А после: «Усе пропало, шеф» ©
      • 0
        > Представьте, что у вас приложение рестартовало по какой-либо причине. Не важно: сетевой сбой, все клиенты отвалились, вы закрыли критическую уязвимость в коде и его нужно перезапустить и пр.
        В этой ситуации как раз все клиенты будут ломиться одновременно.

        Это напомнило, как в прошлом году (?) так упал Скайп. На винду приехало критическое обновление и огромное количество клиентов перезагрузилось, суперноды не выдержали возросшей нагрузки, сеть легла на два дня
  • 0
    Я дописал сервер на Perl (повесил pull request) и погонял тесты у себя на машине. Что странно, цифры получаются совершенно иные:
    РеализацияВремя на подсоединение (среднее)Задержка средняя)СообщенийСоединенийТаймаутов соединения
    Erlang4.0083.595203259100000
    Go2.2911.289204493100000
    Perl2.2661.937204526100000
    • +4
      Нда. Я так и думал, что table в комментариях не работает. Хоть бы из списка html-тегов в этом случае его удалили! :(
      # Реализация  Handshake  Задержка  Сообщений  Соединений  Таймаутов
      # Erlang      4.008      3.595     203259     10000       0
      # Go          2.291      1.289     204493     10000       0
      # Perl        2.266      1.937     204526     10000       0
      

      Тестировал 30 секунд а не 300, т.к. в текущей версии есть баг из-за которого при запуске на 60 и более секунд тест начинает жрать всю память и падает.
      • 0
        ЧТД.
        • –2
          Ну, не знаю, что ЧТД, показывает, что GC-шный VM-ный Erlang не намного хуже компилируемого Go ;) Правда, непонятно, почему задержка настколько выше
          • НЛО прилетело и опубликовало эту надпись здесь
            • –1
              Спецификации железа указаны по ссылке. Использовались medium инстансы EC2.
            • +1
              Вы в код тестов заглядывали? Везде минимальная реализация вебсокет-сервера же!
              Вот для Node github.com/ericmoritz/wsdemo/blob/master/competition/wsdemo.js
              30 строчек всего, остальное — наиболее популярная WebSocket библиотека.
              И где здесь можно ошибиться и проявить свое «неумение писать на чем-то кроме эрланга»? Как вы бы написали?
              • НЛО прилетело и опубликовало эту надпись здесь
                • +2
                  Учитывая что многие держат свои продакшн сервера в облаках, не вижу смысла бенчмаркать на реальном железе, не там, где будет продакшн.

                  А IO если и перекособочивает, то для всех одинаково.
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • +2
                      В облаках дорого, пока есть большая нагрузка, а как она прошла, опять дёшево. Такая ценовая политика всегда найдёт своего клиента.

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

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

                      • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        А каким компилятором компилили на go? Стандартным или gcc?
        • 0
          Стандартным go-1.0.1. Версия erlang R15B.
          • 0
            Если Вас не затруднит. Перетесте пожалуйста с gcc компилятором.
            • 0
              Затруднит. В Hardened Gentoo текущий стабильный gcc — 4.5.3, а в нём нет поддержки gccgo. Ставить нестабильный 4.6 и возиться с этим времени и желания нет.
      • 0
        А версию на libev + EV + AnyEvent можно?
        • 0
          Так оно через libev/EV и работает. IO::Stream это просто надстройка над EV для удобства.

          Что касается AnyEvent, то мне не нравится сама идея такого модуля. Я несколько лет назад очень активно потестировал все перловские event-loop-ы, и выяснилось, что под высокой нагрузкой единственный модуль, который работает во-первых надёжно и во-вторых без утечек памяти — это EV. Так что выбор движка для event loop это серьёзный вопрос, и писать код который работает на «любом движке» — это круто в теории, а на практике я предпочитаю использовать только надёжные модули.
          • 0
            Тогда код положи, пожалуйста, куда-нибудь. Я пока ставлю пакеты на ubuntu :)
          • 0
            Так AnyEvent же определяет EV и работает через него? Да и писал их один и тот же автор.
            • 0
              AnyEvent работает через Any Event. :) И хотя этим Any может оказаться и EV, но гарантий нет. Так что я предпочитаю работать через гарантированно надёжный EV, а не через какой повезёт Any.
              • 0
                SUPPORTED EVENT LOOPS/BACKENDS ^

                The available backend classes are (every class has its own manpage):

                Backends that are autoprobed when no other event loop can be found.

                EV is the preferred backend when no other event loop seems to be in use. If EV is not installed, then AnyEvent will fall back to its own pure-perl implementation, which is available everywhere as it comes with AnyEvent itself.

                Документация обнадёживает что будет выбран в первую очередь именно EV.
                А мне интерфейс AnyEvent почему-то больше нравиться чем EV…
      • 0
        Не подтверждаю твоих данных.
        go/node/erlang отработало ок

        haskell, perl и python жёстко таймаутит

        ruby сказало buffer overflow позорно
        • 0
          Я посмотрел, остальные в кучу потоков идут
          Сделал тоже кучу в твой код, таймаутить перестало.
  • +1
    Почему, интересно, для хаскеля взяли Snap, а не Warp?
  • НЛО прилетело и опубликовало эту надпись здесь
    • –1
      Ну да, ну да. Ведь у всех всегда под рукой есть готовое пустое железо для тестов.
      • НЛО прилетело и опубликовало эту надпись здесь
        • +1
          > У тех, кто хочет получить вменяемые результаты, а не странную хуйню вроде «отзыв 20 секунд» — конечно есть. Такие дела.

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

          > Уверен, там можно еще и до кода докопаться. Просто нет смысла смотреть при таком подходе.

          А, ну понятно. Лишь бы язык почесать.
          • НЛО прилетело и опубликовало эту надпись здесь
            • –3
              Для идиотов на танках повторю: не нравится? Код в руки и вперед опровергать. Языком молоть каждый может
              • НЛО прилетело и опубликовало эту надпись здесь
                • –2
                  Еще раз повторю:
                  1. Свободное пустое железо для тестов под руками не у каждого валяется
                  2. Учитывая, сколько сервисов работает в облаках, тестирование в облаках тоже списывать со счетов глупо
                  3. Если есть пустое железо для тестов — вперед. Код на Гитхабе, проводите тесты, никто вас не останавливает. Молоть языком может каждый
                  4. Если не нравится код тестов, — вперед. Код на Гитхабе, предлагайте изменения, улучшайте тесты, никто вас не останавливает. Молоть языком может каждый

                  Но если вы способны только молоть языком, то увы.
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • –3
                      Ну да. Конструктив, безусловно, — это назвать авторов теста дебилами. Я продолжил разговор исключительно в этом же, безусловно конструктивном, ключе. Не нравится? К психиатру.
                      • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                А вы-то проверяли перед тем как постить топик? ;)
                • 0
                  Моя задача была — помолоть языком, я ее выполнил :)
                  • +1
                    Мужик
    • +1
      То есть вы утверждаете, что Ноде и Питону мешает виртуалка? Почему же она Эрлангу не мешает справляться с задачей? Не находите логических нестыковок в своих претензиях?
      • НЛО прилетело и опубликовало эту надпись здесь
        • +3
          А вы не думали, что человек хотел оттестировать именно результаты для «ксеновская виртуалка»? Учитывая, что сейчас все таи или иначе в облаках, это кажется весьма актуальным. К тому же, условия в плане виртуалки, у всех претендентов одинаковые.

          P.S. Зачем так грубо отзываться о человеке, который приложил усилия и поделился своими результатами со всеми. Пусть они даже на ваш взгляд не верны, они все-равно пока куда весомей чем ваши доводы.
          • НЛО прилетело и опубликовало эту надпись здесь
            • +1
              А продакшн сервера под гипервизором можно держать?
  • +1
    Странно что нет «идеального» (наиболее близкого к ОС) кода на С или С++.
    Так не очень понятно, хорошие эти числа или плохие.
    • +1
      «Близкий к ОС код на С/C++» != идеальный. Потому что на том же Erlang'е 10 000 одновременных подсоединений можно легко обработать в 10 000 потоков, чего не сделаешь на C/C++.
      • 0
        Если у Сишника есть хоть какой-то опыт работы с сетью, то он никогда не будет усложнять себе жизнь и заниматься работой с сетевыми подключениями в тредах. Обработку риквестов, которые будут приходить от этих сокетов сишники могут выносить в треды, но не обслуживание соединений.
        • 0
          Вот пришло нам одновременно 100-1000-10000 реквестов. Выносим все в треды? ;)
          • 0
            Зависит от того над чем работаем. Если риквесты не требуют никакого IO, то здесь нет никаких проблем и мы можем поднимать кол-во тредов==кол-ву логических процессоров.
            Если есть IO, то тут возникает выбор:
            — если работа с легаси кодом, то придётся в тред пул загонять обработку риквестов
            — если сишник ленив, то тоже в тред пул
            — геморрой, с которым как-то справляются любители node.js'а, когда всё превращается в кашу из коллбэков
            — protothreads — это набор макросов, нечто похожее на async в C#
            — можно поэкспериментировать с gcc split stacks и получим легковесные треды вроде тех что в Go
            • 0
              Ну, то есть приходим к следствию Армстронга ;)

              В итоге такой код будет далеко не идеальным и далеко не близким к ОСи ;)
              • 0
                Там же про распределённое программирование, а не про конкарренси.

                В итоге код будет работать и выполнять свои задачи. Не все проблемы удачно вписываются под ерланг, тк можно в разы увеличить эффективность, используя другие механизмы для параллелизма в сложных системах.
                • 0
                  Ну, распределенного не будет без параллельного :)
                  • 0
                    Представьте систему к которой подключено N клиентов, каждые 10мс происходит перерасчёт данных, данные сильно связаны между собой, на сях всё это хозяйство реализовано так:
                    Всё разбито на подзадачи, например: пересчитать положение объектов X, сделать действия Y которые зависят от положения объектов X, выполнить сложные действия, которые зависят от всех остальных задач итд. Дальше всё это естественно выстраивается в граф и планировщик начинает каждые 10мс запускать в тредах всё это хозяйство и уведомлять клиентов об изменениях на которые они подписаны. Увы, но на ерланге всё это превратится в нереально тормозное и корявое поделие.
                    Ерланг отлично справляется с тем для чего он был сделан, перекачивать данные из одного места в другое, но так же очень ужасен для громадного количества других задач.
                    • +3
                      Что за бредятина :) На Erlang'е это спокойно уложится в дерево супервизоров, а «планировщик» пишется в три с половиной строчки кода.

                      > Ерланг отлично справляется с тем для чего он был сделан, перекачивать данные из одного места в другое

                      Бгггг
                      • 0
                        Да писал я на ерланге ещё лет 6 назад, достаточно хорошо знаю как он работает. То что я описал никоим образом не связано с супервизорами, на ерланге эта задача решалась бы совсем иначе, каждый объект в системе был бы актором и все друг друга бы пинали сообщениями, так раньше и было реализовано на Сях до того как не понадобилось добавить параллелизм для обработки больших объёмов данных(не уменьшения задержек). Потуги как-то ускорить всё это тупым обвешиванием блокировок и запуском внутри планировщика как в эрланге захлебнулись в блокировках и не дали нужного результата. В итоге отказались от таск параллелизма, а использовали дата параллелизм и граф задач, которые обходит эти данные.
                        Попытаться решить эту проблему таким же способом в ерланге, используя свой планировщик и несколько акторов с большими ets'ками/list'ами и прочим отсутствием нормальных структур данных превратятся в ещё больший ужас.
                        • –1
                          > обработки больших объёмов данных

                          Вот ключевой момент, а не бредятина про то, как «граф задач будет тормозить на Эрланге».
                          • 0
                            >> Ерланг отлично справляется с тем для чего он был сделан, перекачивать данные из одного места в другое

                            >Бгггг

                            >> обработки больших объёмов данных

                            >Вот ключевой момент

                            Ключевой момент в том что следствие Армстронга с его ерлангом, который реализуется модель акторов с таск параллелизмом работает только на определённом кругу задач, где не нужно обрабатывать данные, а гонять из одного конца в другой, например типичные веб приложения, где вся нагрузка на БД или мессенджеры.
                            • –1
                              > Всё разбито на подзадачи, например: пересчитать положение объектов X, сделать действия Y которые зависят от положения объектов X, выполнить сложные действия, которые зависят от всех остальных задач итд. Дальше всё это естественно выстраивается в граф и планировщик начинает каждые 10мс запускать в тредах всё это хозяйство и уведомлять клиентов об изменениях на которые они подписаны. Увы, но на ерланге всё это превратится в нереально тормозное и корявое поделие.

                              Без уточнения «большие объемы данных» весь текст выше про «тормозное поделие» является бредом, потому что прекрасно ложится на Erlang.
                              • 0
                                >потому что прекрасно ложится на Erlang
                                Да, на ерланге можно написать свой планировщик, вместо тредов ОС использовать акторы и обходить этими акторами список задач, которые будут обрабатывать данные и использовать параллелизм. Но зачем тогда тут ерланг вообще? Если на Си это делается проще и работает на порядки быстрее.
                                Ерланг выигрывает там где идеально вписываются его акторы, иначе ерланг создаёт больше проблем чем решает.
                                • –1
                                  Блин. Вы шутите или на полном серьезе?

                                  Читаем: Всё разбито на подзадачи… всё это естественно выстраивается в граф и планировщик начинает каждые 10мс запускать в тредах… уведомлять клиентов об изменениях на которые они подписаны.

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

                                  Треды, уведомления, граф задач.
                                  Процессы, сообщения, граф задач.

                                  Но да, но да, надо рогом упереться в слово параллелизм, как если бы в эрланге все и всегда обязано обрабатываться параллельно.
                                  • 0
                                    >Но да, но да, надо рогом упереться в слово параллелизм
                                    Нет, пускай у нас всё будет выполняться не параллельно, это как бы пофиг. Треды ОС тоже этого не гарантируют.

                                    struct Object_X {
                                      PositionAndVelocity *pv;
                                      float temperature;
                                    }
                                    
                                    struct Object_Area {
                                      Rect r;
                                      float temperature;
                                      Array<Object_X> xs;
                                    }
                                    
                                    struct Data {
                                      Array<PositionAndVelocity> object_x_pvs;
                                      Array<Object_X> xs;
                                      Array<Object_Area> areas;
                                    }
                                    
                                    task_update_positions(Data *d) {
                                      for (p in d->pvs) {
                                        update_position(p);
                                      }
                                    };
                                    
                                    @ depends(task_update_positions)
                                    task_update_area_temperatures(Data *d) {
                                      for (a in d->areas) {
                                        update_area_temperature(a);
                                      }
                                    }
                                    
                                    @ depends(task_update_area_temperatures)
                                    simulate(Data *d) {};
                                    

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

                                    В ерланге такое можно даже не выдумывать, тк в случае с ерлангом всё будет тормознее чем если взять тупо акторов(Object_X), которые при изменении их позиции будут перекидываться сообщениями между собой, добавляться в акторы(Object_Area) и при изменении температуры так же плеваться сообщениями и всё будет работать, работать на порядки медленее чем то что можно сделать на Си.
                                    • –1
                                      Переведем на Erlang

                                      > Планировщик стартует треды

                                      Планировщик стартует процессы (причем в случае с supervision tree — со встроенными способами мониторинга за состоянием процесса и т.п.)

                                      > тк мы определили все зависимости задач

                                      тк мы определили все зависимости задач

                                      > во время параллельного запуска эти задачи не модифицируют данные друг друга

                                      во время параллельного запуска эти задачи не модифицируют данные друг друга

                                      > взять тупо акторов(Object_X), которые при изменении их позиции будут перекидываться сообщениями между собой, добавляться в акторы(Object_Area) и при изменении температуры так же плеваться сообщениями

                                      взять тупо gen_server'ов или просто процессов Object_X, которые при изменении их позиции будут перекидываться сообщениями между собой, добавляться в акторы(Object_Area) и при изменении температуры так же плеваться сообщениями

                                      Но да, но да. Используя полностью терминологию Erlang'а, и описывая архитектуру, под которую Erlang заточен, мы продолжаем утверждать, что это в Erlang'е будет криво и тормознуто :))) Дададада, точно кривее и тормознутее, чем написанная на коленке точно такая же система на С (в полном сооответсвии с дополнением Армстронга), потому что в С/С++ все это придется изобретать с нуля (в худшем случае).

                                    • –1
                                      Ну и продолжу:
                                      > Да, на ерланге можно написать свой планировщик, вместо тредов ОС использовать акторы и обходить этими акторами список задач, которые будут обрабатывать данные и использовать параллелизм. Но зачем тогда тут ерланг вообще? Если на Си это делается проще и работает на порядки быстрее.

                                      В C появились планировщики задач?
                                      В С появились внятные способы запуска и мониторинга процессов/потоков?
                                      В С появились сообщения для общения между этими потоками?

                                      Или это все придется реализовывать ручками? (Ну или собирать по кусочкам из библиотек)
                                      • 0
                                        >взять тупо gen_server'ов
                                        это я как раз и описывал как делал бы на ерланге, поэтому такое сходство, тк от реализации того что описал выше нет никакого профита в ерланге.
                                        и уж gen_server'ы с их оверхедом я бы не брал, еслиб было так критично по производительности.

                                        >описывая архитектуру, под которую Erlang заточен
                                        shared nothing actors ерланга != задачи, которые не модифицируют данные друг друга
                                        единственный способ, с помощью которого мы можем как-то получить доступ к общим данным насколько помню — это только ets, иначе придётся перекидывать громадные массивы данных между акторами.

                                        >В C появились планировщики задач?
                                        планировщик задач так тяжело написать? В данном примере спокойно будет работать примитивный планировщик, без всяких task stealing'ов, которые реализованы в ерланге.
                                        Если нужны более мощные, конфигурируемые планировщики, то всегда под рукой есть intel tbb.

                                        >В С появились внятные способы запуска и мониторинга процессов/потоков?
                                        если вы про аналог легковесных акторов, то не появилось, но в большинстве случаев не нужны все возможности акторов, а если прижмёт, то не так тяжело дописать какой-то функционал для protothreads или как-то иначе решить проблему. Но в задаче, которую я описывал выше — вообще не уместны акторы/protothreads итд.

                                        >В С появились сообщения для общения между этими потоками?
                                        Не всегда нужна какая-то богатая система для общения между потоками(например в задаче, которую я описывал выше — не нужна) или если вы опять про богатый функционал акторов, то в protothreads написан примитив, поверх которого легко добавить сообщения.
                                        • –1
                                          Еще раз повторю. Опираясь только на это описание задачи:
                                          Всё разбито на подзадачи, например: пересчитать положение объектов X, сделать действия Y которые зависят от положения объектов X, выполнить сложные действия, которые зависят от всех остальных задач итд. Дальше всё это естественно выстраивается в граф и планировщик начинает каждые 10мс запускать в тредах всё это хозяйство и уведомлять клиентов об изменениях на которые они подписаны.

                                          эта задача идеально подходит для Эрланга.

                                          Что тут спорить, я вообще не понимаю.

                                          Но!

                                          Если у нас появляется доп. условие, как-то: «большие объемы данных», то да, Erlang может не подойти.

                                          Я это написал еще пять сообщений тому назад.

                                          Вы мне начинаете рассказывать сказки про кривизну решения на Erlang'е, рассказывая какой-то бред про параллелизм, про толпу каких-то кубиков и наколенных решений в С, в то в время как проблема лежит не в параллелизме, не в акторах, не в оверхедах gen_server'ов, не в «сложных сообщениях» и т.п.

                                          • 0
                                            >Я это написал еще пять сообщений тому назад.
                                            Я просто подумал, что:
                                            ">> Ерланг отлично справляется с тем для чего он был сделан, перекачивать данные из одного места в другое

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

                                            >про толпу каких-то кубиков и наколенных решений в С
                                            да, мужики из ерланга ограничиваются только OTP и никогда не используют сторонние решения. Что за идиоты придумали cpan, rubygems, pypi когда нужно использовать только стандартную библиотеку, а всё остальное — это какое-то наколенное решение, ведь планировщик, обмен сообщениями — это такие сложные вещи которые должны быть в стандартной либе, а ещё лучше в самом рантайме :)

                                            >Вы мне начинаете рассказывать
                                            Я лишь хотел привести пример, когда ерланговая модель акторов не справляется со своей задачей, раз уж вы заговорили о том как любая система в итоге реализует урезаный вариант ерланга с его распределённостью и параллелизмом.
                                            • –1
                                              > да, мужики из ерланга ограничиваются только OTP и никогда не используют сторонние решения.

                                              Вы опять несете какую-то чушь. Я говорю о том, что «криво реализуемая фигня на Erlang'е», которую вы описываете, на Erlang'е уже давным давно реализована и является частью языка и библиотеки (граф. процессов, процессы, сообщения, callback'и и т.п.)

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

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

                                              Но вы то решили говорить не о них. Вы решили рассказать бредятину про то, как на эрлнаге сложно реализовать взаимодействие процессов :-\
                                              • 0
                                                >про толпу каких-то кубиков и наколенных решений в С
                                                >Я говорю о том, что «криво реализуемая фигня на Erlang'е», которую вы описываете, на Erlang'е уже давным давно реализована и является частью языка и библиотеки

                                                Так и я об этом написал :) О том что всё что уже реализовано в рантайме или стандартной либе — это труъ, а всё что в библиотеках, как например intel tbb, это для неудачников, которые не знают что в ерланг рантайме всё встроено :)

                                                >Вы решили рассказать бредятину про то, как на эрлнаге сложно реализовать взаимодействие процессов
                                                Ну вы же поняли, что я описывал что эрланг пригоден только для перекидывания данных из одного места в другое, а для обработки данных он как-то совсем не очень, если только под обработкой не понимается отрендерить шаблон и подставить в него какие-то данные ;)

                                                А вообще всё началось с разрыва мозга про то что любая система, в которой нужна _конкарренси_ в итоге реализует какую-то часть ерланга, хотя там было написано про распределённую систему, но вы зачем-то потом добавили бредятину про параллелизм, который опять никоем местом не относился к теме :) На что я рассказал историю о том что особого профита от ерлангового параллелизма мы не можем получить, тк параллелизм штука сложная и то что подходит для решения одной задачи будет полным гавном для решения другой задачи.
  • 0
    Можете протестировать github.com/kakserpom/phpdaemon?
    • –2
      Это не ко мне, это к автору на Гитхабе :)
  • 0
    Так и не смог запустить тест:

    ./runtest results/java.dat 300 192.168.1.8 8000 10000
    Running test with 10000 clients for 300 seconds
    Data File: "results/java.dat"
    escript: exception error: undefined function wsdemo_logger:new/1
      in function  runtest__escript__1339__771169__243679:main/1
      in call from escript:run/2
      in call from escript:start/1
      in call from init:start_it/1
      in call from init:start_em/1
    


    Огорчился.
  • 0
    Две слабеньких ноды на одной клиент на другой сервер (ubuntu 12.04 64bit, Intel Core i5 M450 (1 core), 1GB)
    Получился такой результат:
                               erlang         go python torna    node.js    
    clients                      2746       2851         2763       7002
    handshakes                   2744       2850         2761       2933
    connection_timeouts             0          0            0       2728
    messages_recv              555231     564177       519975      61927
    handshake_time.median      75.666     13.107      162.254   2227.526
    message_latency.median    447.559     486.75     2047.321  98011.552
    crashes                         0          0            0          0
    

    • 0
      Примерно одинаковые результаты получились из-за того что клиент уперся в ресурсы, добавил ему ядро и памяти:
                                 erlang         go   py_tornado    node.js    
      clients                     10000      10000        10000      10000
      handshakes                   4285       3989         4594       1926
      connection_timeouts          5478       4531         5406       8074
      messages_sent             1015680     993991      1280922     556111
      messages_recv              713854     776522       293795     179100
      handshake_time.median    1657.051     24.955      993.679   1945.153
      message_latency.median  40455.355  32573.558    98749.899  96158.056
      crashes                         0          0            0          0

      Думаю что реализацию python tornado для этого теста можно неплохо улучшить, т.к. сейчас у него большой показатель «connection_timeouts», — сервер показывает очень много закрытий потоков, (видимо таймаут со стороны клиента) — а каждое закрытие вызывает исключение — с формированием полного tracaback и в консоль валиться «тонна» логов — это не такие уж и легкие блокирующие операции.
      • 0
        Было бы здорово увидеть исходники того что вы тестили или это те же тесты что и в начале статьи?
        • 0
          Это те же тесты, с githab'a. Конфигурация сервера другая.
          • 0
            О чем и говорилось выше… Все это — синтетика.
            • +1
              Несинтетических тестов вообще не бывает.
              • 0
                Я не против )) Вопрос только в том, как преподносятся результаты. Хотя я, повторю, люблю и ноду (которая ни в какие ворота, судя по тестам), и испытываю уважение к Эрлангу (который красавчик получился).
                • 0
                  Результаты преподносятся так, как преподносятся. В случае с этими тестами, в отличие от многих других, в том, что можно указать автору на ошибки, исправить тест и запустить тест самому. Что уже во много раз лучше, чем Debian Shootout, например
  • 0
    Вот тут blog.virtan.com/2012/07/million-rps-battle.html аналогичное тестирование между C/C++/Java/Erlang/NodeJS/Python/Perl. Результаты несколько отличаются.
    • –1
      Джавист у вас походу совсем никакой… как можно было потерять столько пакетов?
      Или же у вас с тестом не все в порядке.
      • +1
        При такой нагрузке пакеты теряются на всех узлах.
        Впрочем, код тестов в открытом доступе. У вас есть возможность возразить аргументированно прислав патч. Результаты тестов с ним опубликую.
  • +1
    вторая часть бенчмарка «вышла», к слову eric.themoritzfamily.com/websocket-demo-results-v2.html

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