Acredito que a comunidade Erlang não tenha inveja do Node.js, pois faz E / S não-bloqueadora nativamente e tem maneiras de escalar implantações facilmente para mais de um processador (algo que nem mesmo está embutido no Node.js.). Mais detalhes em http://journal.dedasys.com/2010/04/29/erlang-vs-node-js e Node.js ou Erlang
E o Haskell? O Haskell pode fornecer alguns dos benefícios do Node.js., ou seja, uma solução limpa para evitar o bloqueio de E / S sem recorrer à programação multithread?
Há muitas coisas atraentes no Node.js
- Eventos: Sem manipulação de encadeamento, o programador fornece apenas retornos de chamada (como na estrutura Snap)
- É garantido que os retornos de chamada sejam executados em um único encadeamento: nenhuma condição de corrida é possível.
- API agradável e simples, compatível com UNIX. Bônus: Excelente suporte HTTP. DNS também disponível.
- Cada E / S é por padrão assíncrona. Isso facilita evitar bloqueios. No entanto, muito processamento da CPU em um retorno de chamada afetará outras conexões (nesse caso, a tarefa deve ser dividida em subtarefas menores e agendada novamente).
- Mesmo idioma para o lado do cliente e do servidor. (No entanto, não vejo muito valor neste. JQuery e Node.js compartilham o modelo de programação de eventos, mas o resto é muito diferente. Não vejo como o compartilhamento de código entre o lado do servidor e o lado do cliente poderia ser útil na prática.)
- Tudo isso embalado em um único produto.
Respostas:
Ok, então, tendo assistido um pouco da apresentação do node.js. que @gawi me indicou, posso dizer um pouco mais sobre como Haskell se compara ao node.js. Na apresentação, Ryan descreve alguns dos benefícios do Green Threads, mas continua dizendo que não considera a falta de uma abstração de thread uma desvantagem. Eu discordo da posição dele, particularmente no contexto de Haskell: acho que as abstrações que os threads fornecem são essenciais para tornar o código do servidor mais fácil de acertar e mais robusto. Em particular:
o uso de um encadeamento por conexão permite escrever um código que expresse a comunicação com um único cliente, em vez de escrever um código que lide com todos os clientes ao mesmo tempo. Pense assim: um servidor que lida com vários clientes com threads é quase o mesmo que um que lida com um único cliente; a principal diferença é que há um
fork
lugar no primeiro. Se o protocolo que você está implementando é complexo, gerenciar a máquina de estado para vários clientes simultaneamente fica bastante complicado, enquanto os encadeamentos permitem apenas script da comunicação com um único cliente. O código é mais fácil de acertar e mais fácil de entender e manter.retornos de chamada em um único encadeamento do SO são multitarefa cooperativa, em oposição à multitarefa preventiva, que é o que você obtém com os encadeamentos. A principal desvantagem da multitarefa cooperativa é que o programador é responsável por garantir que não haja fome. Perde modularidade: cometa um erro em um só lugar e pode estragar todo o sistema. Isso é realmente algo com o qual você não quer se preocupar, e a preempção é a solução simples. Além disso, a comunicação entre retornos de chamada não é possível (seria um impasse).
a concorrência não é difícil no Haskell, porque a maioria dos códigos é pura e, portanto, é segura para threads por construção. Existem simples primitivas de comunicação. É muito mais difícil dar um tiro no pé com simultaneidade em Haskell do que em um idioma com efeitos colaterais irrestritos.
fonte
Sim, de fato, eventos e threads são unificados no Haskell.
Na verdade , os encadeamentos são implementados em termos de eventos e são executados em vários núcleos, com migração contínua de encadeamentos, desempenho e aplicativos documentados.
Por exemplo, para
Coleções simultâneas nbody em 32 núcleos
Em Haskell, você tem eventos e threads, e como todos os eventos estão ocultos.
Leia o documento que descreve a implementação.
fonte
Primeiro, não entendo que o node.js está fazendo a coisa certa, expondo todos esses retornos de chamada. Você acaba escrevendo seu programa no CPS (estilo de passagem de continuação) e acho que deve ser o trabalho do compilador fazer essa transformação.
Portanto, com isso em mente, você pode escrever usando um estilo assíncrono, se desejar, mas, ao fazer isso, perderá a escrita em um estilo síncrono eficiente, com um encadeamento por solicitação. Haskell é ridiculamente eficiente em código síncrono, especialmente quando comparado a outros idiomas. Está tudo embaixo.
Você ainda pode ter uma condição de corrida no node.js, mas é mais difícil.
Cada solicitação está em seu próprio encadeamento. Quando você escreve um código que precisa se comunicar com outros threads, é muito simples torná-lo seguro, graças às primitivas de simultaneidade do haskell.
Dê uma olhada no hackage e veja por si mesmo.
Você não tem esses problemas, o ghc distribuirá seu trabalho entre os threads reais do SO.
Haskell não pode ganhar aqui ... certo? Pense novamente, http://www.haskell.org/haskellwiki/Haskell_in_web_browser .
Baixe ghc, acenda a cabala. Há um pacote para todas as necessidades.
fonte
Pessoalmente, vejo o Node.js e a programação com retornos de chamada como algo desnecessariamente de baixo nível e um pouco artificial. Por que programar com retornos de chamada quando um bom tempo de execução, como o encontrado no GHC, pode lidar com retornos de chamada para você e com eficiência?
Enquanto isso, o tempo de execução do GHC melhorou bastante: agora apresenta um "novo novo gerente de IO" chamado MIO, onde "M" significa multicore. Ele é baseado no gerente de E / S existente e seu principal objetivo é superar a causa da degradação do desempenho de mais de 4 núcleos. Os números de desempenho fornecidos neste documento são bastante impressionantes. Veja você mesmo:
E:
Mio chegou à versão 7.8.1 do GHC. Pessoalmente, vejo isso como um grande passo à frente no desempenho de Haskell. Seria muito interessante comparar o desempenho de aplicativos Web existentes compilado pela versão anterior do GHC e 7.8.1.
fonte
Eventos IMHO são bons, mas a programação por meio de retornos de chamada não é.
A maioria dos problemas que torna especial a codificação e a depuração de aplicativos da Web vem do que os torna escaláveis e flexíveis. O mais importante, a natureza sem estado do HTTP. Isso aprimora a navegabilidade, mas impõe uma inversão de controle em que o elemento IO (o servidor da Web neste caso) chama diferentes manipuladores no código do aplicativo. Esse modelo de evento - ou modelo de retorno de chamada, mais precisamente dito - é um pesadelo, pois os retornos de chamada não compartilham escopos variáveis e uma visão intuitiva da navegação é perdida. É muito difícil evitar todas as possíveis alterações de estado quando o usuário navega para frente e para trás, entre outros problemas.
Pode-se dizer que os problemas são semelhantes à programação da GUI, onde o modelo de evento funciona bem, mas as GUIs não têm navegação nem botão de retorno. Isso multiplica as transições de estado possíveis em aplicativos da web. O resultado da tentativa de resolver esse problema são estruturas pesadas com configurações complicadas, muitos identificadores mágicos difundidos sem questionar a raiz do problema: o modelo de retorno de chamada e sua falta inerente de compartilhamento de escopos variáveis e sem sequenciamento, portanto a sequência deve ser ser construído através da ligação de identificadores.
Existem estruturas sequenciais, como o ocsigen (ocaml) à beira-mar (smalltalk) WASH (descontinuado, Haskell) e o mflow (Haskell) que resolvem o problema do gerenciamento de estado, mantendo a navegabilidade e a plenitude do REST. dentro dessas estruturas, o programador pode expressar a navegação como uma sequência imperativa em que o programa envia páginas e aguarda respostas em um único encadeamento, as variáveis estão no escopo e o botão voltar funciona automaticamente. Isso produz inerentemente um código mais curto, mais seguro e mais legível, onde a navegação é claramente visível para o programador. (aviso justo: sou o desenvolvedor do mflow)
fonte
A questão é bastante ridícula porque 1) Haskell já resolveu esse problema de uma maneira muito melhor e 2) aproximadamente da mesma maneira que Erlang. Aqui está a referência em relação ao nó: http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks
Dê ao Haskell 4 núcleos e ele pode fazer 100k (simples) solicitações por segundo em um único aplicativo. O nó não pode fazer o mesmo número e não pode escalar um único aplicativo entre núcleos. E você não precisa fazer nada para colher isso, porque o tempo de execução Haskell é non-blocking. A única outra linguagem (relativamente comum) que possui E / S não bloqueadora incorporada no tempo de execução é o Erlang.
fonte
pm2 -i max path/to/app.js
será automaticamente dimensionado para o número ideal de instâncias com base nos núcleos disponíveis. Além disso, o Node também não é bloqueado por padrão.Assim como o nodejs eliminou a libev, o Snap Haskell Web Framework também eliminou a libev .
fonte