Je fais un jeu de simulation de gestion, quelque chose comme Roller Coaster Tycoon. Je veux savoir quelle est la meilleure façon de structurer mes objets univers afin de maximiser les performances.
Disons que j'ai 5000 personnes dans mon jeu que je pourrais:
Créez un objet et stockez-les dans un tableau comme celui-ci;
class person() {
this.x = 0;
this.y = 0;
this.thirst = 15;
this.hunger = 15;
// etc.. add methods:
public findPath(int destX, int destY) {
// and so on
}
people = new person[5000];
for (int = 0; i < 5000; i++) {
people[i] = new person;
}
Ou devrais-je faire un objet de personnes qui contient de nombreux tableaux d'octets représentant des attributs de personnes comme ceci:
class people() {
this.hunger = new byte[5000]
this.thirst = new byte[5000]
getThirst(int i) {
return this.thirst[i]
}
// and so on....
Ou suis-je totalement hors de propos?
java
architecture
data-structure
ali_goes_oosh
la source
la source
Réponses:
La terminologie courante est "structure de tableaux" (SOA) et "tableau de structures" (AOS) qui viennent de C et sont le plus souvent considérés en termes de travail SIMD.
En règle générale, l'approche AOS est plus rapide, si elle est utilisée de manière appropriée, mais SOA a tendance à être plus facile à travailler (et donc à optimiser pour la qualité la plus importante - le temps de développement).
SOA, en particulier en Java, signifie que vos données peuvent rester serrées en mémoire. Vous pouvez parcourir les propriétés et vous attendre à ce que le cache du processeur et autres restent satisfaits. Avec AOS, en particulier en Java, chaque objet finit par être alloué "quelque part" en mémoire. Itérer sur des objets peut potentiellement détruire votre cache CPU assez fortement.
En fin de compte, je choisirais l'approche que vous trouvez la plus facile à utiliser. Votre temps de développement est beaucoup plus précieux que si votre jeu prend en charge des PC de 10 ans ou seulement des PC de 9 ans (il est très peu probable que vous fassiez quoi que ce soit qui nécessite le dernier matériel).
la source
Il n'y a aucune raison pour que vous ne puissiez pas avoir les deux, en utilisant le modèle Facade pour traduire d'une interface à l'autre représentation sous-jacente. Par exemple, en utilisant les termes SOA / AOS de Sean:
Façade SOA
Façade AOS
De cette façon, vous pouvez choisir librement entre un formulaire que vous êtes à l'aise d'utiliser , en tant qu'interface développeur, ou tout ce qui est le mieux en tant qu'implémentation pour une raison quelconque, y compris des raisons d'efficacité / de cache.
Un autre avantage de la façade est qu'elle conduit très naturellement au motif Flyweight , où vous utilisez une interface pour représenter beaucoup plus de personnes que ce qui est réellement en mémoire. Par exemple, vous avez peut-être des clients robotiques qui n'ont jamais soif; alors vous pouvez mettre ce cas spécial dans votre
PersonFacade
, et les utilisateurs de cette interface n'auront jamais à connaître les robots:... ou en utilisant une approche plus OO, vous auriez une
Robot
classe distincte qui agit exactement comme unePerson
exception pourgetThirst()
.la source
Fabriquez des objets et stockez-les dans un tableau! Faire des tableaux pour la faim et la soif peut économiser un peu d'espace et fonctionner plus rapidement dans certaines situations simples, mais ce n'est pas de la POO. Java et OOP feront beaucoup pour vous si vous leur donnez une chance. Pour un jeu vraiment simple, votre deuxième exemple pourrait bien fonctionner, mais même alors, vous devriez pratiquer vos compétences OO. Votre première approche fonctionnera bien pour vous, peu importe l'ampleur, la complexité et la pilosité de votre programme.
Pensez à toutes les fois où il sera utile de récupérer un
Person
objet à partir d'une requête. Qui a envoyé ce message? par exemple. Beaucoup de méthodes que vous écrivez voudront savoir à qui elles ont affaire. Et vous aurez beaucoup de méthodes qui s'intégreront bien dans unePerson
classe appropriée . SiPerson
est statique ou singleton, où mettez-vous des méthodes qui agissent sur des personnes individuelles?Si jamais vous faites du multithreading - et avec 5000 utilisateurs vous pourriez être poussé dedans - vous trouverez l'instance parent pour chaque utilisateur beaucoup plus pratique.
(Et ce groupe de personnes: respectez-le pour l'instant, mais à un moment donné, vous voudrez d'autres périphériques de stockage. Une carte en quelque sorte afin que vous puissiez trouver des personnes par nom. Et peut-être plusieurs listes avec des clés différentes, et probablement des grappes de répertorie chacune suffisamment courte pour être des tableaux ou des listes liées.)
la source