Pergunta

Se você aderiu ao paradigma da programação funcional, é provável que goste de Erlang e Haskell.Ambos têm núcleos puramente funcionais e outras vantagens, como threads leves, que os tornam adequados para um mundo multicore.Mas também existem algumas diferenças.

Erlang é uma linguagem tolerante a falhas comprovada comercialmente com um modelo de distribuição maduro.Ele tem um recurso aparentemente único em sua capacidade de atualizar sua versão em tempo de execução por meio do carregamento de código a quente.(Forma legal!)

Haskell, por outro lado, possui o sistema de tipos mais sofisticado de qualquer linguagem convencional.(Onde eu defino 'mainstream' como qualquer linguagem que tenha um livro publicado da O'Reilly, então Haskell conta.) Seu desempenho de thread único em linha reta parece superior ao de Erlang e seus threads leves também parecem ainda mais leves.

Estou tentando montar uma plataforma de desenvolvimento para o resto da minha vida de codificação e queria saber se seria possível misturar Erlang e Haskell para alcançar a melhor plataforma da categoria.Esta questão tem duas partes:

  1. Eu gostaria de usar o Erlang como uma espécie de MPI tolerante a falhas para unir as instâncias de tempo de execução do GHC.Haveria um processo Erlang por tempo de execução do GHC.Se "o impossível acontecesse" e o tempo de execução do GHC morresse, o processo Erlang detectaria isso de alguma forma e morreria também.Os recursos de carregamento e distribuição de código quente do Erlang continuariam a funcionar.O tempo de execução do GHC pode ser configurado para usar apenas um núcleo, ou todos os núcleos da máquina local, ou qualquer combinação entre eles.Depois que a biblioteca Erlang foi escrita, o restante do código de nível Erlang deve ser puramente padronizado e gerado automaticamente por aplicativo.(Talvez por uma DSL Haskell, por exemplo.) Como alguém consegue pelo menos algumas dessas coisas?
  2. Gostaria que Erlang e Haskell pudessem compartilhar o mesmo coletor de lixo.(Esta é uma ideia muito mais avançada do que 1.) Linguagens executadas na JVM e no CLR alcançam maior massa compartilhando um tempo de execução.Entendo que há limitações técnicas para executar Erlang (carregamento de código ativo) e Haskell (polimorfismo de tipo superior) na JVM ou no CLR.Mas que tal desagregar apenas o coletor de lixo?(Uma espécie de início de tempo de execução para linguagens funcionais.) Obviamente, a alocação ainda teria que ser muito rápida, então talvez esse bit precise ser vinculado estaticamente.E deve haver algum mecanismo para distinguir o heap mutável do imutável (incluindo memória lenta de gravação única), pois o GHC precisa disso.Seria viável modificar tanto o HIPE quanto o GHC para que os coletores de lixo pudessem compartilhar uma pilha?

Por favor, responda com quaisquer experiências (positivas ou negativas), ideias ou sugestões.Na verdade, qualquer feedback (exceto abuso direto!) É bem-vindo.

Atualizar

Obrigado por todas as 4 respostas até agora - cada uma me ensinou pelo menos uma coisa útil que eu não sabia.

A respeito de o resto da vida de codificação coisa - incluí-o ligeiramente irónico para desencadear o debate, mas é realmente verdade.Há um projeto que tenho em mente e no qual pretendo trabalhar até morrer e que precisa de uma plataforma estável.

Na plataforma que propus acima, eu escreveria apenas Haskell, já que o padrão Erlang seria gerado automaticamente.Então, quanto tempo Haskell durará?Bem, Lisp ainda está conosco e não parece que irá desaparecer tão cedo.Haskell é código aberto BSD3 e alcançou massa crítica.Se a programação em si ainda existir daqui a 50 anos, eu esperaria que Haskell, ou alguma evolução contínua de Haskell, ainda estivesse aqui.

Atualização 2 em resposta à postagem de rvirding

Concordo - implementar uma máquina virtual universal "Erskell/Haslang" completa pode não ser absolutamente impossível, mas certamente seria muito difícil.Compartilhando apenas o nível do coletor de lixo como algo como uma VM, embora ainda difícil, parece uma ordem de magnitude menos difícil para mim.No modelo de coleta de lixo, as linguagens funcionais devem ter muito em comum - a unbiquidade de dados imutáveis ​​(incluindo conversões) e a exigência de alocação muito rápida.Portanto, o fato de que a semelhança está intimamente ligada às VMs monolíticas parece um tanto estranho.

As VMs ajudam a atingir a massa crítica.Basta ver como linguagens funcionais 'leves' como F# e Scala decolaram.Scala pode não ter a tolerância absoluta a falhas de Erlang, mas oferece uma rota de fuga para muitas pessoas que estão ligadas à JVM.

Ao ter uma única pilha faz mensagem passando muito rápido ele introduz uma série de outros problemas, principalmente que fazer GC se torna mais difícil, pois tem que ser interativo e globalmente não interruptivo para que você não pode usar os mesmos algoritmos mais simples como o modelo de heap por processo.

Com certeza, isso faz todo o sentido para mim.As pessoas muito inteligentes da equipe de desenvolvimento do GHC parecem estar tentando resolver parte do problema com um GC paralelo de “parar o mundo”.

http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel-gc/par-gc-ismm08.pdf

(Obviamente, "parar o mundo" não funcionaria para Erlang geral, dado seu principal caso de uso.) Mas mesmo nos casos de uso em que "parar o mundo" é aceitável, suas acelerações não parecem ser universais.Portanto, concordo com você, é improvável que exista um GC universalmente melhor, razão pela qual especifiquei na parte 1.da minha pergunta que

O tempo de execução do GHC pode ser configurado para usar apenas um núcleo, ou todos os núcleos na máquina local, ou qualquer combinação intermediária.

Dessa forma, para um determinado caso de uso, eu poderia, após o benchmarking, escolher seguir o caminho Erlang e executar um tempo de execução GHC (com um GC singlethreaded) mais um processo Erlang por núcleo e deixar Erlang copiar a memória entre núcleos para uma boa localidade .

Alternativamente, em uma máquina com processador duplo com 4 núcleos por processador com boa largura de banda de memória no processador, o benchmarking pode sugerir que eu execute um tempo de execução GHC (com um GC paralelo) mais um processo Erlang por processador.

Em ambos os casos, se Erlang e GHC pudessem compartilhar um heap, o compartilhamento provavelmente estaria vinculado a um único thread do sistema operacional em execução em um único núcleo de alguma forma.(Estou me exagerando aqui, e é por isso que fiz a pergunta.)

Também tenho outra agenda - benchmarking de linguagens funcionais independentemente do GC.Muitas vezes leio sobre resultados de benchmarks de OCaml v GHC v Erlang v ...e me pergunto o quanto os resultados são confundidos pelos diferentes GCs.E se a escolha do GC pudesse ser ortogonal à escolha da linguagem funcional?Afinal, quão caro é o GC?Veja esta postagem no blog dos advogados do diabo

http://john.freml.in/garbage-collection-harmful

por meu amigo Lisp, John Fremlin, ao qual ele, encantadoramente, deu o título de seu post "Coleta automatizada de lixo é lixo".Quando John afirma que o GC está lento e não acelerou tanto, eu gostaria de poder contra-atacar com alguns números.

Foi útil?

Solução

Muitas pessoas de Haskell e Erlang estão interessadas no modelo em que Erlang supervisiona a distribuição, enquanto Haskell executa os nós de memória compartilhada em paralelo, fazendo todo o processamento/lógica de números.

Um começo para isso é a biblioteca haskell-erlang: http://hackage.haskell.org/package/erlang

E temos esforços semelhantes na terra Ruby, via Hubris: http://github.com/mwotton/Hubris/tree/master

A questão agora é encontrar alguém que realmente avance na interoperabilidade Erlang/Haskell para descobrir os problemas complicados.

Outras dicas

Você vai se divertir misturando GC entre Haskell e Erlang.Erlang usa um heap por processo e copia dados entre processos - como Haskell nem tem um conceito de processos, não tenho certeza de como você mapearia esse GC "universal" entre os dois.Além disso, para melhor desempenho, Erlang usa uma variedade de alocadores, cada um com comportamentos ligeiramente ajustados que, tenho certeza, afetariam o subsistema de GC.

Tal como acontece com todas as coisas no software, a abstração tem um custo.Nesse caso, suspeito que você teria que introduzir tantas camadas para que ambas as linguagens superassem sua incompatibilidade de impedância que você acabaria com uma VM comum de pouco desempenho (ou útil).

Resumindo: aceite a diferença!Há enormes vantagens em NÃO executar tudo no mesmo processo, principalmente do ponto de vista da confiabilidade.Além disso, acho um pouco ingênuo esperar que uma linguagem/VM dure pelo resto da sua vida (a menos que você planeje a.) viver pouco tempo ou b.) se tornar algum tipo de monge de código que SÓ funciona em um único projeto).O desenvolvimento de software envolve agilidade mental e disposição para usar as melhores ferramentas disponíveis para construir código rápido e confiável.

Embora este seja um tópico bastante antigo, se os leitores ainda estiverem interessados, vale a pena dar uma olhada Nuvem Haskell, que traz simultaneidade e distribuição no estilo Erlang para o GHC estável.

O próximo plataforma de processo distribuído biblioteca adiciona suporte para construções do tipo OTP, como gen_servers, árvores de supervisão e várias outras abstrações "com sabor de haskell" emprestadas e inspiradas por Erlang/OTP.

  1. Você poderia usar um processo OTP gen_supervisor para monitorar instâncias Haskell geradas com open_port().Dependendo de como a "porta" saiu, você poderá reiniciá-la ou decidir que ela parou propositalmente e deixar o processo Erlang correspondente morrer também.

  2. Fugheddaboudit.Mesmo essas VMs independentes de idioma de que você fala às vezes têm problemas com dados transmitidos entre idiomas.Você deve apenas serializar os dados entre os dois de alguma forma:banco de dados, XML-RPC, algo assim.

A propósito, a ideia de uma plataforma única para o resto da vida provavelmente também é impraticável.A tecnologia da computação e a moda mudam com muita frequência para esperar que você possa continuar usando apenas um idioma para sempre.Sua própria pergunta aponta isso:nenhuma língua faz tudo o que desejamos, ainda hoje.

Como dizzyd mencionou em seu comentário, nem todos os dados nas mensagens são copiados, grandes binários existem fora dos heaps do processo e não são copiados.

Usar uma estrutura de memória diferente para evitar heaps separados por processo é certamente possível e foi feito em várias implementações anteriores.Embora ter um único heap torna a passagem de mensagens muito rapidamente, ele apresenta uma série de outros problemas, principalmente porque fazer GC se torna mais difícil, pois precisa ser interativo e globalmente não-interruptivo, de modo que você não pode usar os mesmos algoritmos mais simples do modelo de heap por processo.

Contanto que utilizemos estruturas de dados imutáveis, não há problema com robustez e segurança.Decidir quais modelos de memória e GC usar é uma grande compensação e, infelizmente, existe o melhor modelo universalmente.

Embora Haskell e Erlang sejam linguagens funcionais, elas são, em muitos aspectos, linguagens muito diferentes e têm implementações muito diferentes.Seria difícil criar uma máquina "Erskell" (ou Haslang) que pudesse lidar com ambas as linguagens de forma eficiente.Pessoalmente, acho que é muito melhor mantê-los separados e garantir uma interface realmente boa entre eles.

O CLR suporta otimização de chamada final com um explícito tail opcode (usado pelo F#), que a JVM (ainda) não possui equivalente, o que limita a implementação desse estilo de linguagem.O uso de separado AppDomains permite que o CLR faça hot-swap de código (veja, por exemplo, esta postagem do blog mostrando como isso pode ser feito).

Com Simon Peyton Jones trabalhando próximo a Don Syme e a equipe de F# da Microsoft Research, seria uma grande decepção se não víssemos um IronHaskell com algum tipo de status oficial.Um IronErlang seria um projeto interessante - o maior trabalho provavelmente seria portar o agendador de threading verde sem ficar tão pesado quanto o mecanismo de fluxo de trabalho do Windows ou ter que executar uma VM BEAM no topo do CLR.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top