Je travaille sur un jeu vidéo nécessitant des performances élevées, alors j'essaie de configurer une bonne stratégie de mémoire ou une partie spécifique du jeu, la partie qui est le jeu "modèle", la représentation du jeu. p>
J'ai un objet contenant une représentation de jeu entière, avec différents gestionnaires à l'intérieur pour conserver la représentation cohérente, après les règles de jeu. Chaque entité de jeu est actuellement générée par une usine spécifique à un type, j'ai donc plusieurs usines qui me permettent d'isoler et de modifier la gestion de la mémoire de ces entités que je souhaite. P>
Maintenant, je suis en train de choisir entre ces deux alternatives: p>
Maintenant, j'avais des expériences de mondes réelles avec le A donc je ne suis pas expérimenté avec B et que je voudrais des conseils concernant ces solutions, pour un projet à longue durée de vie. Modifier pour clarification: J'utilise C ++ si (ce n'est pas encore clair) p>
6 Réponses :
Je n'ai pas d'expérience spécifique avec le gestionnaire de mémoire que vous envisagez, mais voici quelques directives générales qui peuvent aider: p>
Vous pourriez avoir le meilleur des deux mondes (en supposant que la vitesse est similaire) en développant plusieurs piscines, mais en faisant des tests finaux et la libération de production avec une seule piscine. De cette façon, vous pouvez repérer les problèmes d'allocation / de gestion au cours du développement, mais profitez toujours de la piscine unique potentiellement plus efficace. P>
Lorsque vous dites que 2. Pourrait être plus lent, vous ne voulez pas dire que cela serait plus lent si je n'ai pas plus de 1 allocation / distribution par seconde? (sur un matériel décent) Vous parlez de beaucoup d'allocation / de distribution par secondes?
Je veux dire seulement que 2. pourrait être plus lent s'il utilise une stratégie de gestion de la mémoire différente, ou s'il utilise la même stratégie, mais que la stratégie est sensiblement plus lente si elle gère tous vos objets dans une piscine plutôt que dans des pools séparés. Si vous attendez une allocation / deuxièmement, c'est très i> qu'il y aura une différence de préoccupation rapide.
Une des solutions possibles est quelque chose entre 1. et 2. p>
Utilisez des pools pour petits objets: une piscine par taille d'objet. Dans ce cas, vous pouvez trouver facilement la piscine en stockant des pointeurs dans le tableau. P>
Et en outre, vous pouvez avoir un pool pour les gros objets. Dans ce cas, la fragmentation est moins probable et la tenue de temps n'est pas si critique car les objets importants ne sont pas alloués et traités très fréquemment. P>
Note sur Boost :: Piscine Code>. Lorsque vous testez la performance de
boost :: piscine code>, test non seulement l'attribution, mais également la classique. J'ai vécu que
boost :: piscine code> et
boost :: fast_pool code> Le temps de distribution peut être extrêmement grand. Mon cas était composé d'allocations et de désaffecations de petits objets de différentes tailles dans une piscine p>
La bonne réponse est spécifique à votre domaine problématique. Mais dans les domaines de problèmes que je travaille, le premier est généralement celui que nous choisissons. p>
Je fais du code en temps réel ou proche de temps réel. Édition audio et lecture surtout. Dans ce code, nous ne pouvons généralement pas nous permettre d'attribuer la mémoire du tas dans le moteur de lecture. La plupart du temps, Malloc retourne assez vite, mais parfois ça ne le fait pas. Et cela compte parfois. P>
Nos solutions sont donc d'avoir des pools spécifiques pour certains objets et d'utiliser la piscine générale pour tout le reste. Les piscines spécifiques ont un certain nombre d'éléments préallociés et sont implémentés comme une liste liée (en réalité une file d'attente), de sorte que l'attribution et la libération ne sont jamais plus que quelques mises à jour du pointeur et le coût de la saisie et de la sortie d'une section critique. p>
comme une replie pour des cas inhabituels; Lorsque quelqu'un doit allouer d'une piscine spéciale et qu'il est vide - nous allouerons un morceau de mémoire générale (plusieurs objets) et ajouterons cela au pool spécial. Une fois qu'une allocation fait partie du piscine spécial, elle n'est jamais revenue à la piscine générale tant que l'application se décharge ni ne commence un nouveau projet. P>
Faire de bons choix sur la taille initiale et la taille maximale des piscines spéciaux constitue une partie importante de la réglage de l'application. p>
Un problème que vous rencontrez est que les implémentations STL sont autorisées à supposer que deux allocateurs du même type sont équivalents. C'est la raison pour laquelle Boost.Pool utilise un seul pool (techniquement, il utilise une piscine différente pour chaque type). C'est-à-dire que vos allocateurs ne sont pas autorisés à avoir des membres non statiques dans le cas général. Si vous faites un jeu vidéo et que vous savez que votre implémentation STL n'a pas ce problème, alors ne vous inquiétez pas pour cela - mais il peut y avoir quelques problèmes avec Liste :: Splice Code> et
std :: échange code> sur les conteneurs. p>
En fait, j'irai avec 2. Je peux vous donner un exemple du noyau Linux. Dans le noyau, la dentry (entrée de répertoire) et les objets Inode doivent être mis en cache en mémoire plus longtemps pour une meilleure réactivité aux utilisateurs. Comme l'objet Inode dépend du système de fichiers, chaque système de fichiers créera son propre pool d'objets. Une autre chose que vous pourriez faire si les objets sont similaires consiste à résumer les objets et à conserver des attributs communs dans un objet abstrait et à stocker les informations spécifiques à l'objet à l'aide d'un conteneur. Reportez-vous au code ci-dessous pour une idée complète. P>
Je pense que tu voulais réellement vouloir y aller avec 1? Depuis l'exemple que vous avez donné est en réalité l'option 1 et vous ne l'avez pas critiqué ..
Il n'est pas pratique d'utiliser STL ou Boost pour tout type de jeu vidéo, pour commencer. Vous pouvez être absolument sûr que la seconde que vous utilisez un conteneur STL votre mémoire est fragmentée et que vos performances sont désespérément dans les toilettes par rapport à l'idéal au moins (car la plupart du code de chacun se trouve dans cette catégorie, la plupart des gens ne remarquent jamais et ne peuvent pas vraiment comparer à rien d'autre). Je n'ai pas toujours pensé si fort mais au fil du temps, j'ai vu même quelques lignes de code, c'est comme un peu de Gremlin qui finira par un jour de faire une grande douleur. p>
La première méthode est la plus courante, et comme quelqu'un qui a fait à la fois, c'est probablement le seul moyen qui est pratique si vous ne voulez pas dépenser beaucoup plus de temps et d'énergie sur le problème que cela ne vaut probablement la peine de vous. La deuxième façon est meilleure car il est plus général et pourtant être adapté à vos besoins exacts, mais c'est beaucoup de travail et pas quelque chose à sauter à la légère. P>
"Il n'est pas pratique d'utiliser STL ou Boost pour tout type de jeu vidéo, pour commencer." Une telle chose bizarre à dire. Beaucoup de jeux font simplement une simulation de physique simple et brute sur une douzaine d'objets ou des objets à la fois. Certains sont basés sur le tour. Certains sont basés sur le texte. Les jeux peuvent être écrits en Flash ou JavaScript et réussir. Certains beaux jeux populaires utilisent sûrement STL ou Boost. Tout n'est pas "triple-a".
Il est parfaitement réalisable d'utiliser des bibliothèques STL ou Boost pour créer un jeu vidéo AAA. Cette réponse était de 2009 et ne s'applique plus. La bibliothèque moderne C ++ (qui n'est pas équivalente au terme "stl") est très i> performante et seulement si l'un est paranoïaque ou extrêmement talentueux ou juste curieux voudrait rouler sa propre bibliothèque adaptée spécifiquement à une vidéo Les besoins du jeu.