Question

J'apprends actuellement la programmation fonctionnelle pendant mon temps libre avec Scala et j'ai une question d'inactivité pour les débutants.

Je peux voir l’élégance de disposer d’objets immuables lors du calcul d’une transformée en ondelettes de Haar, c’est-à-dire lorsque les données elles-mêmes représentées par les objets ne changent pas.

Mais j’ai vu un blog où quelqu'un a eu un petit jeu à titre d'exemple pour démontrer l'immutabilité. Si un objet de créature subit des dégâts, il ne change pas d'état - il renvoie un nouvel objet de créature avec les nouveaux points de vie et un nouveau "aggro envers X". drapeau. Mais si nous concevions quelque chose comme un MMORPG, dit World of Warcraft. Une centaine de joueurs sur un champ de bataille ... possiblement des milliers d’attaques et d’effets de sorts d’affaiblissement / atténuation qui les affectent de différentes manières. Est-il encore possible de concevoir le système avec des objets complètement immuables? Pour moi, il semblerait qu'il y aurait un essaim ginormeux de nouvelles instances à chaque "tick". Et pour obtenir l’instance d’objet actuellement valide, tous les clients doivent constamment passer par une sorte de "monde de jeu" central. objet, ou?

La programmation fonctionnelle est-elle adaptée à cela, ou s'agit-il du "meilleur outil du meilleur travail, probablement pas immuable ici"?

Était-ce utile?

La solution

  

Pour moi, il semblerait qu’il y aurait un essaim ginormeux de nouvelles instances à chaque "tick".

En effet, c'est le cas. J'ai une application Haskell qui lit un flux de données de marché (environ cinq millions de messages au cours d'une journée de négociation de six heures, pour les données qui nous intéressent) et maintient "l'état actuel". pour diverses choses, telles que les dernières offres et offres, les prix et les quantités des instruments, l'adéquation de notre modèle au marché, etc. Il est plutôt effrayant de simuler une exécution de ce programme contre un flux enregistré en mode profilage et de regarder il alloue et gère près de 288 To de mémoire vive (soit près de 50 000 fois la taille de la mémoire vive de ma machine) au cours des 500 premières secondes de son exécution. (Le chiffre serait considérablement plus élevé sans profilage, car le profilage ralentit non seulement l’application, mais oblige également son exécution sur un seul cœur.)

Mais gardez à l’esprit que le ramasse-miettes dans les implémentations en langage pur est optimisé pour ce type de comportement. Je suis assez satisfait de la vitesse globale de mon application, et je pense que c'est assez exigeant, dans la mesure où nous devons analyser plusieurs centaines de messages par seconde à partir du flux du marché, faire des calculs assez détaillés pour construire notre modèle et les utiliser. modèle permettant de générer des ordres pour se rendre à la bourse le plus rapidement possible.

Autres conseils

Généralement, en programmation fonctionnelle, vous n’avez pas de constructeur de style C ++. Ensuite, même si, théoriquement, vous créez constamment des objets, cela ne signifie pas que le compilateur doit créer du code pour allouer un nouvel objet, car cela ne peut pas affecter le comportement du programme. Comme les données sont immuables, le compilateur peut voir les valeurs que vous venez de spécifier et ce qui a été transmis à vos fonctions.

Ensuite, le compilateur peut créer un code compilé très strict qui calcule simplement les champs dans les objets spécifiques quand ils sont nécessaires. Son efficacité dépend de la qualité du compilateur utilisé. Cependant, un code de programmation fonctionnel dit au compilateur beaucoup plus à propos de votre code qu’un compilateur C pour un programme similaire ne pourrait le supposer, c’est pourquoi un bon compilateur peut générer un meilleur code que ce à quoi vous pouvez vous attendre.

Donc, du moins en théorie, il n’ya aucune raison de s’inquiéter; les implémentations de programmation fonctionnelle peuvent évoluer aussi bien que les implémentations d'allocation de tas orientées objet. En pratique, vous devez comprendre la qualité de l’implémentation linguistique que vous utilisez.

Un MMORPG est déjà un exemple d'immutabilité. Étant donné que le jeu est distribué sur des serveurs et des systèmes de joueurs, il n’existe absolument pas de solution "Gameworld" centrale. objet. Ainsi, tout objet envoyé sur le réseau est immuable & # 8212; car il n'est pas modifié par le destinataire. Au lieu de cela, un nouvel objet ou message est envoyé en réponse, s’il en existe un.

Comme je n'ai jamais écrit de jeu distribué, je ne sais pas exactement comment il est implémenté, mais je soupçonne que les mises à jour des objets sont calculées localement ou envoyées sous forme de diffs sur le réseau.

Par exemple, vous jouez à Command & amp; Conquérir. Votre tank Mammoth est assis en mode prêt surveillant votre base. Votre adversaire s’approche avec un char léger pour explorer votre base. Votre tank mammouth tire et frappe le tank de votre adversaire, lui causant des dégâts.

Ce jeu est assez simple, donc je suppose que beaucoup est calculé localement autant que possible. Supposons que les ordinateurs des deux joueurs sont initialement synchronisés en termes d'état du jeu. Ensuite, votre adversaire clique pour déplacer son char léger dans votre base. Un message (immuable) vous est envoyé sur le fil. Comme l'algorithme de déplacement d'un réservoir est (probablement) déterministe, votre copie de Command & amp; La conquête peut déplacer le tank de votre adversaire sur votre écran, mettant à jour votre état de jeu (immuable ou mutable). Lorsque le char léger arrive à portée de votre char gigantesque, celui-ci tire. Une valeur aléatoire est générée sur le serveur (dans ce cas, un ordinateur est choisi arbitrairement en tant que serveur) pour déterminer si le coup frappe votre adversaire ou non. En supposant que le char ait été touché et qu'une mise à jour du char de votre adversaire soit effectuée, seul le diff & # 8212; le fait que le nouveau niveau de blindage du char ait été ramené à 22% & # 8212; est envoyé sur le fil pour synchroniser les jeux des deux joueurs. Ce message est immuable.

Que l'objet sur le poste de l'un des joueurs représentant le char soit mutable ou immuable est sans importance; il peut être mis en œuvre de toute façon. Chaque joueur ne change pas directement l'état du jeu des autres joueurs.

Un point à noter sur l’immutabilité est que (si elle est correctement implémentée), la création d’objets est relativement légère. Si un champ est immuable, vous pouvez le partager entre les instances.

Lors de la conception d'un programme fonctionnel, il est important de prendre en compte le fait que les objets immuables présentent une charge supplémentaire. Il est également important de se rappeler que si les objets de votre programme MMORPG sont immuables, ils seront intrinsèquement plus évolutifs. L’investissement initial dans l’équipement est donc peut-être plus élevé, mais à mesure que la situation évoluera, vous pourrez vous adapter à votre base de joueurs.

Une autre chose importante à considérer est qu’à présent, les machines les plus robustes ont 6 cœurs par unité de traitement. Considérez une machine à deux processeurs avec 6 cœurs chacun. Un de ces 12 cœurs peut être en train de ramasser des ordures. Ainsi, le temps système résultant de la destruction d’objets volumineux peut être compensé par l’application facilement évolutive à ces 11 autres cœurs.

N'oubliez pas non plus que tous les objets (et leurs sous-objets) ne doivent pas nécessairement être complètement reconstruits sur une copie. Tout type de référence qui n'a pas changé prendra seulement une assignation de référence lorsqu'un objet est "copié".

Ne pensez pas à la création d’objets au niveau du fil. Par exemple, une exécution optimisée pour un langage fonctionnel pourra probablement "tricher". quand il s'agit de remplacer un objet et de faire une mutation réelle de la structure existante, si elle sait que rien ne référencera l'original et que la nouvelle la remplacera complètement. Pensez à l'optimisation de la récursion de queue, mais appliquée à l'état d'objet.

J'ai trouvé un blog aujourd'hui qui traite EXACTEMENT des questions que j'ai soulevées dans ce post:

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

Comme presque tous les outils de programmation, les objets immuables sont puissants, mais dangereux dans les mauvaises situations. Je pense que l'exemple de jeu n'est pas très bon ou du moins très artificiel.

Eric Lippert a publié des messages intéressants sur le sujet. de l'immuabilité, et ils sont une lecture assez intéressante.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top