it-swarm.com.ru

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

Я полагаю, что сообщество 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. Все это упаковано в один продукт.
214
gawi

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

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

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

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

217
Simon Marlow

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

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

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

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

Например. за

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

alt text

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

Прочтите статью описание реализации.

154
Don Stewart

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

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

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

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

Вы можете по-прежнему иметь состояние гонки в node.js, но это сложнее.

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

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

Взгляните на hackage и убедитесь сами.

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

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

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

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

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

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

18
dan_waterworth

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

Между тем, среда выполнения GHC значительно улучшилась: теперь в нее добавлен "новый новый IO менеджер", называемый MIO , где "M" означает многоядерный, как я полагаю. Он основан на существующем IO менеджере, и его главная цель - устранить причину снижения производительности ядра на 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.

8
vlprans

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

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

5
Greg Weber

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

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

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

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

5
agocorona
1
Chawathe Vipul