Каков ответ Haskell на Node.js? - PullRequest
       321

Каков ответ Haskell на Node.js?

214 голосов
/ 02 октября 2010

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

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


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

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

Ответы [ 7 ]

218 голосов
/ 05 октября 2010

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

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

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

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

154 голосов
/ 02 октября 2010

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

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

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

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

Например, для

Параллельные коллекции nbody на 32 ядра

alt text

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

Прочтите статью , описывающую реализацию.

18 голосов
/ 22 июня 2011

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

События: без манипуляций с потоками, программист обеспечивает только обратные вызовы (как в Snap Framework)

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

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

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

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

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

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

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

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

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

Хаскелл не может здесь выиграть ... верно? Подумайте еще раз, http://www.haskell.org/haskellwiki/Haskell_in_web_browser.

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

Скачать GHC, запустить клику. Есть пакет для каждой потребности.

8 голосов
/ 26 августа 2013

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

Тем временем среда выполнения GHC значительно улучшилась: теперь она имеет «новый новый ввод-вывод».менеджер "звонил MIO , где" М "означает многоядерный, я считаю.Он основан на существующем диспетчере ввода-вывода, и его главная цель - устранить причину снижения производительности ядра на 4+.Показатели производительности, представленные в этой статье, впечатляют.Убедитесь сами:

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

И:

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

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

5 голосов
/ 28 апреля 2013

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

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

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

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

5 голосов
/ 23 июня 2011

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

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

1 голос
/ 18 января 2015
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...