Quand je code dans le moteur, je ne m'inquiète souvent que d'un fixe n
: j'ai déjà une partition spatiale limitant le nombre d'objets recevantupdate()
, physics()
et render()
à peu près ceux sur l' écran et les régions avoisinantes. La taille maximale des lots est généralement assez bien définie par jeu, bien qu'elle soit invariablement un peu plus grande que ce que vous aviez prévu.
Dans ce cas, je ne suis pas autant préoccupé par le big-O que par le multiplicateur à facteur constant et les termes d'ordre inférieur. Pour une fonction avec un runtime comme a*n^2 + b*n + c
(qui est O(n^2)
), je suis souvent beaucoup plus concerné par la réduction a
et éventuellement l'élimination c
. Un coût d'installation ou de démontagec
peut devenir proportionnellement élevé par rapport à un petit n
.
Cependant, cela ne veut pas dire que big-O (ou plus particulièrement big-theta ) est un excellent indicateur d'odeur de code. Voyez O(n^4)
quelque part, ou pire encore une O(k^n)
heure géométrique, et il est temps de vous assurer que vous envisagez d'autres options.
Je suis généralement beaucoup plus préoccupé par l'optimalité du big-O et en sautant à travers des cerceaux pour trouver des algorithmes avec un big-O inférieur lorsque je traite des outils de création de données. Bien que le nombre d'objets dans un niveau / une zone de diffusion donné soit généralement bien défini, le nombre total d'objets / actifs artistiques / fichiers de configuration / etc. sur un jeu entier peut ne pas l'être. C'est aussi un nombre beaucoup plus important. Même en exécutant une marque de données parallèle, nous attendons toujours environ une minute (je sais, pleurnicher - la création de données pour les consoles peut prendre des heures - nous sommes principalement de petits jeux portables) pour passer par unjam data-clean && jam data
cycle.
Pour donner un exemple spécifique: cela est vraiment devenu incontrôlable avec un algorithme de streaming de tuiles en arrière-plan qui diffuse 8x8 256 couleurs. Il est utile de partager des tampons de streaming entre des "couches" d'arrière-plan, et nous pourrions avoir jusqu'à 6 d'entre elles à un niveau donné partageant le même tampon. Le problème est que l'estimation de la taille du tampon nécessaire est basée sur les positions possibles des 6 couches - et s'il s'agit d'un nombre premier largeur / hauteur / taux de défilement, vous commencez rapidement à lancer une recherche exhaustive - qui commence à approcherO(6^numTiles)
- qui est dans la catégorie "plus longtemps que l'univers ne sera autour" dans de nombreux cas. Heureusement, la plupart des cas ne sont que 2 à 3 couches, mais même dans ce cas, nous dépassons la durée d'une demi-heure. Pour le moment, nous échantillonnons un très petit sous-ensemble de ces possibilités, augmentant la granularité jusqu'à ce qu'une durée définie se soit écoulée (ou nous avons terminé la tâche, ce qui peut arriver pour les petites configurations à double couche). Nous augmentons un peu cette estimation en nous basant sur des statistiques antérieures de la fréquence à laquelle nous nous sommes trompés, puis nous ajoutons un peu de rembourrage supplémentaire pour faire bonne mesure.
Un autre exemple amusant: sur un jeu PC il y a quelque temps, l'ingénieur principal a expérimenté pendant un certain temps avec des listes de sauts . La surcharge de mémoire finit par provoquer plus d'effets de cache, ce qui ajoute une sorte de multiplicateur non constant à toute l'affaire - donc ce ne sont vraiment pas un bon choix pour les petits n
. Mais pour les listes triées plus importantes où les recherches sont fréquentes, elles offrent un avantage.
(Je trouve souvent que l'algorithme naïf est un big-O plus élevé, plus rapide sur les petits ensembles de données et plus facile à comprendre; les plus intéressants / complexes (par exemple, trie patricia) sont plus difficiles à comprendre et à maintenir pour les gens, mais des performances plus élevées sur les plus grands ensembles de données.)