Pergunta

Atualmente estou aprendendo programação funcional no meu tempo livre com Scala, e tenho uma pergunta newbie ocioso.

Eu posso ver a elegância de ter objetos imutáveis ??ao fazer algo como calcular um Haar transformada wavelet -. Ou seja, quando os dados em si sendo representados pelos objetos não muda

Mas eu vi um blog onde alguém tinha um pequeno jogo como um exemplo ao demonstrar imutabilidade. Se um objeto criatura recebeu dano, ele não mudou seu estado - ele retornou um novo objeto criatura com os novos pontos de vida e um novo "aggro em direção X" bandeira. Mas se tivéssemos que projetar algo como um MMORPG, World of Warcraft dizer. Uma centena de jogadores em um campo de batalha ... possivelmente milhares de ataques e polimento / debuffing efeitos de magia que os afetam de diferentes maneiras. Ainda é possível projetar o sistema com objetos completamente imutáveis? Para me afigura-se como haveria um enxame ginormous de novos casos cada 'tick'. E para obter a instância actualmente em vigor de objetos, todos os clientes que constantemente tem que passar por algum tipo de objeto central "gameworld", ou?

O escala de programação funcional para isso, ou isso é um caso de "melhor ferramenta para melhor trabalho, provavelmente não imutável aqui"?

Foi útil?

Solução

Para me afigura-se como haveria um enxame ginormous de novos casos cada 'tick'.

Na verdade, esse é o caso. Tenho uma aplicação Haskell que lê um feed de dados de mercado (cerca de cinco milhões de mensagens ao longo de um dia de negociação de seis horas, para os dados em que estamos interessados) e mantém "estado atual" para várias coisas, tais como a a maioria dos recentes preços de compra e venda e quantidades para os instrumentos, o quão bem o nosso modelo se encaixa no mercado, etc. etc. é um pouco assustador para simular uma corrida deste programa contra um feed gravado no modo de perfil e vê-lo alocar e GC perto de 288 TB de memória (ou próximo a 50.000 vezes o tamanho da RAM da minha máquina) nos primeiros 500 segundos de sua corrida. (O número seria consideravelmente maior sem profiling, uma vez profiling não só retarda a aplicação, mas também as forças de tudo para ser executado em um núcleo, também.)

Mas tenha em mente, o coletor de lixo em implementações de linguagem pura é otimizado para esse tipo de comportamento. Estou muito feliz com a velocidade total da minha candidatura, e eu acho que é bastante exigente, em que temos de analisar várias centenas de mensagens por segundo a partir da alimentação do mercado, fazer alguns cálculos bastante extensos para construir nosso modelo, e o uso que modelo para gerar ordens de ir para a troca o mais rápido possível.

Outras dicas

Normalmente na programação funcional você não terá construtores estilo C ++. Então, embora conceitualmente você está criando objetos o tempo todo, isso não significa que o compilador tem de tornar o código para alocar um novo objeto, porque ele não pode afetar o comportamento do programa. Desde que os dados é imutável, o compilador pode ver quais os valores que você acabou especificado, e que foi passado em suas funções.

Em seguida, o compilador pode criar um código realmente apertado compilado que apenas calcula os campos no específica objetos quando eles são necessários. Como isso funciona bem depende da qualidade do compilador que você usa. No entanto, o código de programação funcional limpo diz o compilador bastante mais sobre o código de um compilador C para um programa similar poderia supor, e assim, portanto, um bom compilador pode gerar um código melhor do que o que você poderia esperar.

Assim, pelo menos em teoria, não há nenhuma razão para se preocupar; implementações de programação funcional pode escalar tão bem como orientado a objeto pilha de alocar implementações. Na prática, você precisa entender a qualidade da implementação da linguagem que você está trabalhando.

Um MMORPG é um exemplo de imutabilidade. Desde que o jogo é distribuído entre servidores e sistemas dos jogadores, há absolutamente não é um 'gameworld' objeto central. Assim, qualquer objeto que é enviado sobre o fio é imutável - porque não se trocar pelo receptor. Em vez disso, um novo objeto ou uma mensagem é enviada como uma resposta, se houver um.

Eu nunca escrevi um jogo distribuído então eu não sei exatamente como eles estão implementadas, mas eu suspeito que as atualizações para objetos ou são computados localmente ou enviado como diffs sobre o fio.

Por exemplo, você está jogando Command & Conquer. Seu tanque de mamute está sentado no modo pronto guardando sua base. Seu oponente se aproxima com um tanque de luz para explorar a sua base. Seu tanque de mamute tiros e acerta tanque do seu oponente, causando danos.

Este jogo é bastante simples, então eu suspeito um lote é calculado localmente sempre que possível. Suponha que os computadores dos dois jogadores são inicialmente em sincronia em termos de estado do jogo. Em seguida, seu adversário clica para mover o seu tanque de luz em sua base. Uma mensagem (imutável) é enviado a você sobre o fio. Desde o algoritmo para mover um tanque é (provavelmente) determinista, sua cópia de Command & Conquer pode mover tanque do seu oponente em sua tela, atualizar seu estado de jogo (pode ser imutável ou mutável). Quando o tanque de luz vem em conjunto de seu tanque gigantesco, seus fogos de tanque. Um valor aleatório é gerado no servidor (neste caso, um computador é escolhido arbitrariamente como o servidor) para determinar se o tiro atinge o seu adversário ou não. Assumindo que o tanque foi atingido e uma atualização para o tanque do seu oponente deve ser feita, somente o diff - o fato de que o nível de armadura nova do tanque diminuiu para 22% - é enviado através do fio para sincronizar jogos os dois jogadores. Esta mensagem é imutável.

Se o objeto no computador, quer do jogador que representa o tanque é mutável ou imutável é irrelevante; ele pode ser implementado de qualquer forma. Cada jogador não alterar diretamente o estado de jogo de outros jogadores.

Um ponto a nota sobre a imutabilidade é que (se implementado corretamente) que faz a criação do objeto relativamente leve. Se um campo é imutável, então ele pode ser compartilhada entre instâncias.

É importante a considerar ao projetar um programa funcional que, como você indicar, objetos imutáveis ??terá alguma sobrecarga. Também é importante lembrar que por ter objetos em seu programa de MMORPG ser imutável será inerentemente mais escalável. Assim, o investimento inicial em equipamentos pode ser maior, mas na estrada como as coisas se expandir você será capaz de escalar a sua base de jogadores.

Outra coisa importante a considerar é que agora uma das máquinas mais grossa tem 6 núcleos por processador. Considere-se uma máquina de CPU dupla com 6 núcleos cada. Um desses 12 núcleos pode estar fazendo a coleta de lixo e assim a sobrecarga de derrubar lotes de objetos pode ser compensada pela aplicação ser facilmente escalável para os outros 11 núcleos.

Lembre-se também que nem todos os objetos (e de sub objetos) necessidade de ser totalmente reconstruída em uma cópia. Qualquer tipo de referência que não mudou só terá uma única atribuição de referência quando um objeto é "copiado".

Não pense de criação do objeto no nível fio. Por exemplo, um runtime otimizado para uma linguagem funcional, provavelmente, será capaz de "enganar" quando se trata de substituir uma mutação objeto e fazer real da estrutura existente, se ele não sabe nada irá referenciar o original eo novo substitui-lo completamente. Pense cauda recursão Optimization, mas aplicado ao estado do objeto.

Eu encontrei um blog, hoje, que trata justamente das questões que levantei neste post:

http://prog21.dadgum.com/23.html

Como praticamente todas as ferramentas de programação, Objetos imutáveis ??são poderosos, mas perigoso na situação errada. Eu acho que o exemplo do jogo não é muito bom, ou pelo menos muito artificial.

Eric Lippert tem algumas interessantes sobre o tema de imutabilidade, e eles são bastante uma leitura interessante.

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