2010-10-02 2 views
204

Я считаю, что сообщество Erlang не завидует Node.js, так как оно не блокирует ввод-вывод и имеет способы легко масштабировать развертывания для нескольких процессоров (что-то даже не встроено в Node.js). Более подробная информация на сайте http://journal.dedasys.com/2010/04/29/erlang-vs-node-js и Node.js or ErlangЧто такое ответ Haskell на Node.js?

Что относительно Haskell? Может ли Haskell предоставить некоторые преимущества Node.js, а именно, чистое решение, чтобы избежать блокировки ввода-вывода без использования многопоточного программирования?


Там не много вещей, которые являются привлекательными с Node.js

  1. Событие: Нет манипуляция нити, программист предоставляет только обратные вызовы (например, в рамках оснастки)
  2. Callbacks гарантированно будет работать в одном потоке: невозможно состояние гонки.
  3. Приятный и простой в использовании UNIX-API. Бонус: отличная поддержка HTTP. Также доступен DNS.
  4. Каждый ввод-вывод по умолчанию является асинхронным. Это позволяет избежать блокировок. Однако слишком большая обработка процессора в обратном вызове будет влиять на другие соединения (в этом случае задача должна разделиться на более мелкие подзадачи и перепланировать).
  5. Тот же язык для клиентской и серверной сторон. (Я не вижу слишком большого значения в этом, однако jQuery и Node.js используют модель программирования событий, но все остальное очень отличается. Я просто не вижу, как совместный код между серверной и клиентской стороной может будут полезны на практике.)
  6. Все это упаковано в один продукт.
+16

Я думаю, вы должны задать этот вопрос на [Programmers] (http://programmers.stackexchange.com/). – Jonas

+43

Не включая кусок кода не делает его субъективным вопросом. – gawi

+1

Правда, но Programmers - это не только сайт для субъективных вопросов. Это место для вопросов, которые напрямую не связаны с кодом, например. выбор языка. Хороший вопрос. +1 – Jonas

ответ

212

Итак, посмотрев немного на node.js presentation, на что я указал @gawi, я могу сказать немного больше о том, как Haskell сравнивает с node.js. В презентации Райан описывает некоторые преимущества Green Threads, но затем продолжает утверждать, что он не считает недостаток абстракции нитей в качестве недостатка. Я бы не согласился с его положением, особенно в контексте Haskell: я думаю, что абстракции, которые предоставляют потоки, необходимы для того, чтобы сделать код сервера более понятным и более надежным. В частности:

  • используя один поток для каждого соединения позволяет писать код, выражающую связь с одним клиентом, а что написание кода, который имеет дело с все клиенты одновременно. Подумайте об этом так: сервер, который обрабатывает несколько клиентов с потоками, выглядит почти так же, как тот, который обрабатывает один клиент; главное отличие - есть fork где-то в первом. Если используемый вами протокол является сложным, управление конечным автоматом для нескольких клиентов одновременно становится довольно сложным, тогда как потоки позволяют вам просто сценарировать связь с одним клиентом. Код легче получить, и его легче понять и поддерживать.

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

  • Совместимость в Haskell не является сложной задачей, поскольку большинство кода является чистым и поэтому поточно-безопасным по конструкции. Есть простые примитивы общения. Гораздо сложнее стрелять в ногу с параллелизмом в Haskell, чем на языке с неограниченными побочными эффектами.

+41

Итак, я получаю, что node.js является решением двух проблем: 1- параллелизм в большинстве языков , 2 - использование потоков ОС - экспансивный.Решение js заключается в использовании параллелизма на основе событий (w/libev), чтобы избежать связи между потоками и избежать проблем масштабируемости потоков ОС. У Haskell нет проблемы №1 из-за чистоты. Для # 2 Haskell имеет легкие потоки + менеджер событий, который недавно был оптимизирован в GHC для широкомасштабных контекстов. Кроме того, использование Javascript просто не может быть воспринято как плюс для любого разработчика Haskell. Для некоторых людей, использующих Snap Framework, Node.js «просто плох». – gawi

+4

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

+10

Да! И новое мультиплексирование ввода-вывода в GHC 7 делает еще более надежным создание серверов в Haskell. – andreypopp

153

Может Хаскел предоставить некоторые из преимуществ Node.js, а именно чистый раствор, чтобы избежать блокировки ввода/вывода без необходимости прибегать к программированию многопоточной?

Да, на самом деле события и потоки унифицированы в Haskell.

  • Вы можете запрограммировать явные потоки света (например, миллионы потоков на одном ноутбуке).
  • Or; вы можете программировать в стиле async, управляемом событиями, на основе масштабируемого уведомления о событиях.

Резьбы на самом деле implemented in terms of events и проходят через несколько ядер с непрерывной миграцией потоков с документированной производительностью и приложениями.

E.g. для

Одновременные коллекции Nbody на 32 ядер

alt text

В Haskell у вас есть оба события и темы, и как это все события под капотом.

Read the paper описание реализации.

+2

Спасибо. Мне нужно переварить все это ... Это похоже на специфику GHC. Думаю, все в порядке. Язык Haskell когда-то компилируется GHC. Аналогичным образом платформа Haskell является более или менее временем выполнения GHC. – gawi

+1

@gawi: Это и все другие пакеты, которые попадают прямо в него, так что это полезно прямо из коробки. И это тот же образ, который я видел в своем курсе CS; и лучшая часть заключается в том, что в Haskell нетрудно добиться подобных потрясающих результатов в ваших собственных программах. –

+1

Привет, Дон, как вы думаете, вы могли бы ссылаться на веб-сервер haskell, который лучше всего работает (Warp) при ответе на такие вопросы? Вот довольно актуальный критерий для Node.js: http://www.yesodweb.com/blog/2011/03/preliminary initial-warp-cross-language-benchmarks –

18

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

События: Нет манипуляция нить, программист только предоставляет обратные вызовы (например, в рамках оснастки)

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

Обратные вызовы гарантированно выполняются в одном потоке: без условий гонки.

У вас все еще может быть состояние гонки в node.js, но это сложнее.

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

Приятный и простой в использовании UNIX-API. Бонус: отличная поддержка HTTP. Также доступен DNS.

Взгляните на хакеры и убедитесь сами.

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

У вас нет таких проблем, ghc будет распространять вашу работу среди реальных потоков ОС.

Одинаковый язык для клиентской и серверной сторон. (Я не вижу слишком большого значения в этом, однако JQuery и Node.js используют модель программирования событий, но все остальное очень отличается. Я просто не вижу, как код обмена между серверной и клиентской стороной может будут полезны на практике.)

Haskell не может победить здесь ... верно? Подумайте еще раз, http://www.haskell.org/haskellwiki/Haskell_in_web_browser.

Все это упаковано в одном продукте.

Скачать ghc, fire cab. Для каждой потребности есть пакет.

+0

Я просто играл в адвоката дьявола. Итак, да, я согласен с вашими очками. Кроме объединения на стороне клиента и на стороне сервера. Хотя я думаю, что это технически осуществимо, я не думаю, что это может в конечном итоге заменить всю экосистему Javascript на сегодняшний день (JQuery и друзья). Хотя это аргумент, выдвинутый сторонниками Node.js, я не думаю, что это очень важно. Вам действительно нужно поделиться таким количеством кода между уровнем презентации и вашим бэкэнд? Действительно ли мы стремимся к тому, чтобы программисты знали только один язык? – gawi

+0

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

+0

@ dan_waterworth точно см. [Meteor] (http://meteor.com) или [derby.js] (http://derbyjs.com) – mb21

5

Вопрос довольно смешный, потому что 1) Haskell уже решил эту проблему намного лучше и 2) примерно так же, как и Эрланг. Вот контрольный показатель для узла: http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks

Дайте Haskell 4 ядра и он может делать 100k (простых) запросов в секунду в одном приложении. Узел не может делать столько же и не может масштабировать одно приложение по всем ядрам. И вам не нужно ничего делать, чтобы воспользоваться этим, потому что время выполнения Haskell не блокируется. Единственным другим (относительно общим) языком, который имеет неблокирующий IO, встроенный в среду выполнения, является Erlang.

+14

Смешно? Вопрос не в том, «имеет ли Haskell ответ», а скорее «что такое ответ Haskell». В тот момент, когда вопрос был задан, GHC 7 даже не был выпущен, поэтому Haskell еще не был «в игре» (за исключением, возможно, для фреймворков, использующих libev как Snap). Кроме этого, я согласен. – gawi

+1

Я не знаю, было ли это верно, когда вы отправили этот ответ, но теперь есть, по сути, узловые модули, которые позволяют узловым приложениям легко масштабировать по ядрам. Кроме того, эта ссылка сравнивает node.js, работающую на одном ядре, с haskell, работающим на 4 ядрах. Я бы хотел, чтобы он снова запускался в более справедливой конфигурации, но, увы, репозиторий github исчез. –

+2

Haskell, использующий более 4 ядер, ухудшает производительность приложения. Был документ по этому вопросу, он активно работал, но это все еще проблема. Таким образом, запуск 16 экземпляров Node.js на 16-ядерном сервере, скорее всего, будет намного лучше, чем одно приложение ghc, используя + RTS -N16, который действительно будет медленнее, чем + RTS -N1 из-за этой ошибки времени выполнения. Это потому, что они используют только один IOManager, который будет замедляться при использовании со многими потоками ОС. Я надеюсь, что они исправит эту ошибку, но она существует с тех пор, как я никогда не буду надеяться ... – Kr0e

5

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

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

Можно сказать, что проблемы похожи на программирование GUI, где модель событий работает нормально, но графические интерфейсы не имеют навигации и не имеют кнопки возврата. Это умножает возможные переходы состояний в веб-приложениях. Результатом попытки решить эту проблему являются тяжелые каркасы со сложными конфигурациями с множеством распространенных магических идентификаторов, не подвергая сомнению корень проблемы: модель обратного вызова и присущее ей отсутствие совместного использования областей видимости и отсутствие последовательности, поэтому последовательность должна быть построены путем связывания идентификаторов.

Существуют последовательные каркасы, такие как ocsigen (ocaml) seaside (smalltalk) WASH (прекращено, Haskell) и mflow (Haskell), которые решают проблему управления государством, сохраняя навигацию и REST-полноту. в этих рамках программист может выразить навигацию как императивную последовательность, где программа отправляет страницы и ждет ответов в одном потоке, переменные находятся в области действия, а кнопка «Назад» работает автоматически. Это по своей сути создает более короткий, более безопасный, более читаемый код, где навигация ясно видна программисту. (справедливое предупреждение: я разработчик mflow)

+0

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

+0

Вы правы. Потребовалось три года, чтобы ответить на ваши возражения: https://github.com/transient-haskell – agocorona

+0

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

8

Я лично вижу Node.js и программирование с обратными вызовами как излишне низкоуровневое и немного неестественное. Почему программа с обратными вызовами, когда хорошая среда выполнения, такая как найденная в GHC, может обрабатывать обратные вызовы для вас и делать это довольно эффективно?

В то же время время выполнения GHC значительно улучшилось: теперь он имеет новый «новый менеджер IO» под названием MIO, где «M» означает многоядерность, я полагаю. Он основывается на создании существующего менеджера IO, и его основной задачей является преодоление причины ухудшения производительности 4+ ядер. Показатели производительности, представленные в этой статье, впечатляют. Посмотрите сами:

С Mio реалистичные HTTP-серверы в масштабе Haskell до 20 ядер процессора, достигая максимальной производительности до 6,5x по сравнению с теми же серверами, что и предыдущие версии GHC. Латентность серверов Haskell также улучшена: [...] при умеренной нагрузке, уменьшает ожидаемое время отклика на 5.7x по сравнению с предыдущими версиями GHC

И:

Мы также показываем что с Mio McNettle (контроллер SDN, написанный в Haskell) может эффективно масштабировать до 40+ ядер, достигать более 20 миллионов новых запросов в секунду на одной машине и, следовательно, становится самым быстрым из всех существующих контроллеров SDN.

Mio сделал это в выпуске GHC 7.8.1. Я лично вижу это как важный шаг вперед в исполнении Haskell. Было бы очень интересно сравнить производительность существующих веб-приложений, собранную предыдущей версией GHC и 7.8.1.

2
+1

Как это отвечает на вопрос? – dfeuer

+1

@dfeuer Ссылка должна быть прочитана как, Snap Haskell Web Framework сбросил libev, я не знаю, почему форматирование не работает. Время выполнения узла сервера было связано с Linux libev, когда оно начиналось, и это было Snap Web FrameWork. Haskell с Snap похож на ECMAscript с nodejs, поэтому, как Snap развивается вместе с nodejs, более уместен, чем Haskell, который более справедливо по сравнению с ECMAscript в этом контексте. –

+0

@ Robin Green Спасибо. :) –

Смежные вопросы