Я полагаю, что сообщество Erlang не завидует Node.js, поскольку оно изначально не блокирует ввод-вывод и имеет способы легко масштабировать развертывания на более чем один процессор (что даже не встроено в Node.js). Более подробная информация на http://journal.dedasys.com/2010/04/29/erlang-vs-node-js и Node.js или Erlang
Что насчет Хаскелла? Может ли Haskell обеспечить некоторые преимущества Node.js, а именно чистое решение, позволяющее избежать блокировки ввода-вывода без использования многопоточного программирования?
Есть много вещей, которые привлекательны с Node.js
- События: нет манипуляций с потоками, программист предоставляет только обратные вызовы (как в Snap Framework)
- Обратные вызовы гарантированно выполняются в одном потоке: условия гонки невозможны.
- Хороший и простой UNIX-дружественный API. Бонус: отличная поддержка HTTP. DNS также доступен.
- Каждый ввод / вывод по умолчанию является асинхронным. Это позволяет избежать замков. Однако слишком большая загрузка ЦП в обратном вызове повлияет на другие соединения (в этом случае задача должна быть разбита на более мелкие подзадачи и перепланирована).
- Один и тот же язык для клиентской и серверной сторон. (Однако я не вижу в этом особой ценности. JQuery и Node.js разделяют модель программирования событий, но остальное сильно отличается. Я просто не вижу, как совместное использование кода между серверной и клиентской сторонами могло бы быть полезным на практике.)
- Все это упаковано в один продукт.
Ответы:
Итак, посмотрев небольшую презентацию node.js , на которую указал мне @gawi, я могу сказать немного больше о том, как Haskell сравнивается с node.js. В презентации Райан описывает некоторые преимущества Green Threads, но затем продолжает говорить, что не считает недостатком абстракции потоков недостаток. Я бы не согласился с его позицией, особенно в контексте Haskell: я думаю, что абстракции, которые предоставляют потоки, важны для того, чтобы сделать серверный код более простым и правильным и более надежным. В частности:
использование одного потока для каждого соединения позволяет вам писать код, который выражает связь с одним клиентом, а не писать код, который обрабатывает все клиенты одновременно. Думайте об этом так: сервер, который обрабатывает несколько клиентов с потоками, выглядит почти так же, как сервер, который обрабатывает один клиент; главное отличие в том, что
fork
где-то в первом. Если протокол, который вы реализуете, вообще сложен, управление конечным автоматом для нескольких клиентов становится довольно сложным, тогда как потоки позволяют вам просто написать сценарий связи с одним клиентом. Код легче понять, а также легче понять и поддерживать.обратные вызовы в одном потоке ОС - это совместная многозадачность, в отличие от вытесняющей многозадачности, которую вы получаете с потоками. Основным недостатком совместной многозадачности является то, что программист несет ответственность за отсутствие голода. Он теряет модульность: ошибиться в одном месте, и это может испортить всю систему. Это действительно то, о чем вам не нужно беспокоиться, и упреждение - это простое решение. Более того, связь между обратными вызовами невозможна (это может привести к тупику).
параллелизм не сложен в Haskell, потому что большая часть кода является чистой и поэтому поточно-ориентированной по построению. Есть простые примитивы связи. Гораздо сложнее выстрелить себе в ногу с параллелизмом в Haskell, чем на языке с неограниченными побочными эффектами.
источник
Да, на самом деле события и потоки объединены в Haskell.
Потоки фактически реализованы с точки зрения событий и выполняются на нескольких ядрах, с плавной миграцией потоков, с документированной производительностью и приложениями.
Например, для
Параллельные коллекции nbody на 32 ядра
В Haskell у вас есть как события, так и потоки, а так же все события под капотом.
Прочитайте статью с описанием реализации.
источник
Прежде всего, я не придерживаюсь вашего мнения, что node.js делает правильные вещи, выставляя все эти обратные вызовы. Вы заканчиваете тем, что пишете свою программу в CPS (стиль передачи продолжения), и я думаю, что преобразование должно быть задачей компилятора.
Таким образом, имея это в виду, вы можете писать с использованием асинхронного стиля, если вы того пожелаете, но при этом вы упустите запись в эффективном синхронном стиле с одним потоком на запрос. Haskell невероятно эффективен в синхронном коде, особенно по сравнению с другими языками. Это все события внизу.
Вы можете по-прежнему иметь состояние гонки в node.js, но это сложнее.
Каждый запрос находится в своей собственной теме. Когда вы пишете код, который должен взаимодействовать с другими потоками, очень просто сделать его потокобезопасным благодаря примитивам параллелизма haskell.
Взгляните на hackage и убедитесь сами.
У вас нет таких проблем, GHC будет распределять вашу работу среди реальных потоков ОС.
Хаскелл не может выиграть здесь ... верно? Подумайте еще раз, http://www.haskell.org/haskellwiki/Haskell_in_web_browser .
Скачать GHC, запустить клику. Есть пакет для каждой потребности.
источник
Я лично вижу Node.js и программирование с обратными вызовами как излишне низкоуровневую и немного неестественную вещь. Зачем программировать с обратными вызовами, если хорошая среда выполнения, такая как в GHC, может обрабатывать обратные вызовы и делать это довольно эффективно?
Между тем, время выполнения GHC значительно улучшилось: теперь в нем есть «новый новый менеджер ввода-вывода» под названием MIO, где «M» означает многоядерный, как мне кажется. Он основан на существующем диспетчере ввода-вывода, и его главная цель - устранить причину снижения производительности ядра на 4+. Показатели производительности, представленные в этой статье, впечатляют. Увидеть себя:
И:
Mio сделал это в выпуске GHC 7.8.1. Я лично вижу в этом важный шаг вперед в исполнении Haskell. Было бы очень интересно сравнить производительность существующих веб-приложений, скомпилированных с предыдущей версией GHC и 7.8.1.
источник
ИМХО события хорошие, а программирование с помощью обратных вызовов - нет.
Большинство проблем, которые делают особенным кодирование и отладку веб-приложений, связано с тем, что делает их масштабируемыми и гибкими. Самое главное, природа HTTP без сохранения состояния. Это улучшает навигацию, но это навязывает инверсию управления, когда элемент IO (в данном случае веб-сервер) вызывает разные обработчики в коде приложения. Эта модель событий, или, точнее говоря, модель обратного вызова, является кошмаром, поскольку обратные вызовы не разделяют переменные области действия, и интуитивное представление о навигации теряется. Среди других проблем очень трудно предотвратить все возможные изменения состояния, когда пользователь перемещается назад и вперед.
Можно сказать, что проблемы аналогичны программированию в графическом интерфейсе, где модель событий работает нормально, но в графическом интерфейсе нет навигации и кнопки возврата. Это умножает возможные переходы между состояниями в веб-приложениях. Результатом попытки решить эту проблему являются тяжелые фреймворки со сложными конфигурациями, множество распространенных магических идентификаторов, не ставящих под сомнение суть проблемы: модель обратного вызова и присущее ей отсутствие совместного использования переменных областей, а также отсутствие последовательности, поэтому последовательность должна быть построены путем связывания идентификаторов.
Существуют последовательные структуры, такие как ocsigen (ocaml) seaside (smalltalk) WASH (прекращено, Haskell) и mflow (Haskell), которые решают проблему управления состоянием, сохраняя при этом удобство навигации и полноту REST. в этих рамках программист может выразить навигацию как обязательную последовательность, когда программа отправляет страницы и ожидает ответов в одном потоке, переменные находятся в области видимости, а кнопка «назад» работает автоматически. По своей сути это приводит к созданию более короткого, более безопасного и более читаемого кода, где навигация четко видна программисту. (честное предупреждение: я разработчик mflow)
источник
Вопрос довольно нелепый, потому что 1) Хаскелл уже решил эту проблему гораздо лучше и 2) примерно так же, как Эрланг. Вот эталонный тест по отношению к узлу: http://www.yesodweb.com/blog/2011/03/preditional-warp-cross-language-benchmarks
Дайте Haskell 4 ядра, и он может выполнять 100 тыс. (Простых) запросов в секунду в одном приложении. Node не может делать столько же, и не может масштабировать одно приложение по ядрам. И вам не нужно ничего делать, чтобы пожинать это, потому что среда исполнения Haskell не блокируется. Единственный другой (относительно распространенный) язык, который имеет неблокирующий ввод-вывод, встроенный во время выполнения, - это Erlang.
источник
pm2 -i max path/to/app.js
автоматически масштабируется до оптимального количества экземпляров на основе доступных ядер. Кроме того, по умолчанию Node также не блокируется.Так же , как nodejs упал libev Привязать Haskell Web Framework упал libev тоже.
источник