Aidez nous a financer le site: Joignez l'utile à l'agréable et profitez d'FR-Minecraft sans publicités en
devenant VIP ! Ou ajoutez FR-Minecraft dans vos exceptions, nous n'abusons pas des pubs
Cela ressemble à un crie de désespoir, ce message que sp614x a posté sur son forum dédié à son Mod Optifine. Il introduit ainsi son discours:
"Minecraft 1.8 a tellement de problème de performance que je ne sais pas par quoi commencer".
sp614x, peut être ce nom vous est inconnu, c'est pourtant une figure majeure de la communauté, puisqu'il est l'auteur du célèbre Mod Optifine. Optifine est certainement le mod le plus populaire de Minecraft, réputé pour les améliorations des performances qu'il propose au jeu, sp614x propose aux joueurs de finir le travail que Mojang ne fait pas.
Il y a quelques mois, Mojang avait proposé à sp614x de lui racheter son Mod, ce qu'il a refusé. Une bonne nouvelle pour la communauté, car c'est probablement grâce a lui que Minecraft 1.8 gagnera peut être en performance! Car en créant ce Mod, il a montrer ses talents de développeur, et sa réputation l'a suivit jusque chez Mojang qui écoute désormais ses conseils attentivement :-)
Revenons à son message:
Pourquoi Minecraft 1.8 est si lent ?
Pour des raisons techniques, que je vais essayer de vous expliquer quelque soit votre niveau, malheureusement cet article restera particulièrement technique, soyez attentif.
Avant de pouvoir expliquer cela, il faut comprendre ce que c'est que Java, et ses spécificités.
Java n'est pas seulement un language de programmation, c'est un environnement d'éxécution virtuel que l'on appelle une machine virtuel (
VM), une sortie d'ordinateur dans l'ordinateur. Cela à des avantages, et des inconvéniants:
- Avantage: Il est très facile de faire des logiciels multiplateformes (windows, mac, linux), puisque la machine virtuel Java peut être installée sur tous ces systèmes
- Inconveniant: Lorsque cette machine virtuelle execute un logiciel en java, elle même utilise le CPU de l'ordinateur, ce qui au final ralenti le logiciel. Certains annoncent que la baisse des performances est limité (20%), mais longtemps les gens ont reproché à Notch ce choix de Java, qui limite inévitablement les performances globales, c'est pourquoi certains demandent une réécriture complète de Minecraft dans un language comme C++ qui n'a pas ce problème
- Autre avantage: La machine virtuel Java gèrent de manière automatique et transparente une grosse partie du travail du développeur: l'allocation de la mémoire. Pour fonctionner tous les logiciels ont besoin de mémoire (pour mémoriser la position des blocs, le contenu de l'inventaire, etc...), beaucoup de mémoire. Cette mémoire est un composant qui existe physiquement dans l'ordinateur, c'est la mémoire vive (les barettes de RAM). Cette mémoire est partagé entre tous les logiciels qui tourne sur l'ordinateur, c'est pourquoi il est important de savoir la gérer (en prendre une partie, mais pas trop pour en laisser pour les autres). Dans un logiciel classique, c'est le développeur qui doit explicitement demander au système d'exploitation de réserver de l'espace mémoire quand il en a besoin, puis de libérer cette mémoire quand il a terminé, afin de pouvoir la réutiliser plus tard, ou de laisser un autre logiciel la réserver à son tour. La gestion de la mémoire est une tache fastidieuse, peut interressante, et dangeureuse: si on oublie de libérer la mémoire non utilisé, on risque de la remplir (on parle de saturation), provoquant le plantage du logiciel, on appelle cela une fuite mémoire (réservation de mémoire non utilise). Java simplifie cela en réservant automatiquement la mémoire quand le logiciel en a besoin, et en libérant la mémoire quand elle n'est plus utilisé, on appelle ce processus le ramasse miette (plus souvent appellé par son nom anglais le garbage collector,
GC). C'est une opération complexe qui scan l'ensemble des objets mémoires réservés par le logiciel, puis qui analyse leurs interactions pour déterminer lesquels sont utilisés et lesquels peuvent être libérés. Ensuite le garbage collector libère les objets et la RAM utilisé se réduit, sans risque de saturation de la mémoire.
Vous avez peut être remarqué, dans Minecraft, en mode debug, vous avez en haut à droite de l'écran la consommation mémoire qui est affiché:
Ce nombre augmente en permanence de manière linéaire, et parfois redescent, par saut important.
La baisse de la valeur par saut correspond à l'éxécution du garbage collector qui a libéré la mémoire non utilisé.
Si je vous explique cela, c'est parce que selon sp614x le problème de performance de la 1.8 est directement lié à cette gestion de la mémoire.
Voici une traduction de ses explications:
Le problème principal et le plus horrible avec Minecraft 1.8 est l'allocation mémoire. Actuellement le jeu réserve environ 50Mo de mémoire par seconde lorsque le joueur est immobile, et jusqu'à 200Mo/s en mouvement. C'est juste fou.
Que se passe-t-il lorsque un jeu réserve 200Mo par seconde de mémoire, et la libère immédiatement après ?
1 - Avec la limite par défaut de 1Go (soit 1000 Mo) et une utilisation moyenne de 200Mo chaque seconde, Java est obligé de lancer le garbage collector au moins toutes les 4secondes, sinon la mémoire sera saturé (et le jeu plantera). À 60fps (images par seconde), une image s'affiche en 16ms. Afin de ne pas ralentir le jeu, l'opération ne devrait pas durée plus de 10 à 15ms. Dans un temps minimal, il devra déterminer lesquels parmis la centaine de millier d'objets nouvellement créer en mémoire peuvent être libéré et lesquels ne le peuvent pas. C'est un boulot énorme qui neccessite un processeur très puissant pour le faire en moins de 10ms.
2 - Pourquoi ne pas réserver plus de mémoire ?
Réservons 4Go de RAM à Minecraft. Pour cela vous aurez besoin d'avoir au moins 8Go de mémoire dans votre ordinateur car la mémoire rééllement utilisé par le jeu est le double de celle vu par Java. Si la VM décide d'utiliser l'ensemble de la mémoire alloué, cela espacera les cycles du garbage collector (20 secondes au lieu de 4), mais cela augmentera également leur durée par 4, donc toutes les 20 secondes vous auriez un ralentissement.
3 - Pourquoi ne pas utiliser la garbage collection incrémentale ? (ndt: gérer la mémoire en continue)
La dernière version du launcher Minecraft active la gestion de la mémoire en continue par défaut, ce qui en théorie doit remplacer un gros cycle du garbage collector par plein de petits cycles incrémentaux. Le problème c'est que la durée de ces cycles et l'instant de leur execution est trés aléatoire. Cependant ils sont plus court (peut être 50%) qu'un cycle complet. Cela signifie que les FPS commence a varié de manière aléatoire, et que les joueurs subissent des piques de lag régulier. Un FPS constant avec des piques de lag réguliers ont été remplacé par un FPS variable avec des piques de lag aléatoires. Cette stratégie ne fonctionne que si vous avez un processeur puissant, pour que les piques de lag soit suffisant court pour être imperceptible.
4 - Comment cela fonctionnait dans les Releases précédentes ?
Les versions précédentes était beaucoup moins gourmandes en mémoire. Le code original de Notch (jusqu'à la Release 1.3) alloué entre 10 et 20 Mo par seconde, ce qui était beaucoup plus facile à gérer et optimiser. Le rendu à lui seul ne consommait que 1 à 2 Mo par seconde, il était créer spécifiquement pour consommer le moins de ressource possible (réutilisation de buffer, etc.). Avec 200Mo/s on repousse les limites et on force le GC a faire beaucoup plus de travail qui prend du temps. S'il était possible de controller comment et quand le GC fonctionne, peut être il serait possible de mieux répartir le travaille du GC pour le rendre imperceptible. Malheureusement Java ne permet pas actuellement ce genre de controle.
5 - Pourquoi Minecraft 1.8 consomme autant de mémoire ?
C'est la partie la plus interressante: plus de 90% des allocations mémoires ne sont pas du tout néccessaires. La majorité de la mémoire est alloué pour rendre la vie des développeurs plus facile.
- La majorité des objets qui sont alloué sont abandonné immédiatement
- Toutes les fonctions qui avant utilisaient 3 paramètres x, y, z (de type valeur, sans besoin d'allocation mémoire) ont été remplacé par un seul paramètre "BlockPos" (de type objet, qui néccessite d'allouer de la mémoire) qui sont immutable (non modifiable). Cela signifie que si vous voulez modifier la valeur, vous
devez instancier un nouvel objet. C'est un gachi énorme de la mémoire.
- Le chargement des chunks réserve énormement de mémoire juste pour envoyer les données. L'éxécuse sera certainement le "multithreading", cependant ce n'est pas du tout neccessaire (regardez Optifine 1.7).
- Et la liste continue encore et encore ...
Globalement le problème est que les developpeurs ne se soucient pas de la gestion mémoire et utilise les méthodes de developpement à la mode sans chercher à comprendre les conséquences. La mode étant que "immutable c'est bien", "alloué de la mémoire est plus rapide que le cache", " le GC est rapide en ce moment", etc.
Aloué de la mémoire est réellement plus rapide que le cache (Java est même plus rapide que C++ pour la gestion de la mémoire dynamique), mais la libération de la mémoire n'est pas plus rapide, et n'est pas prévisible du tout. Minecraft est une application "temps-réel" et a besoin d'un framerate (fps) stable, et pour cela il doit garder une utilisation mémoire minimal, ou bien gérer lui même sa libération de sa mémoire, ce qui n'est pas possible actuellement avec Java.
6 - Que peut-on faire pour corriger ce problème ?
Si il y a 2 ou 3 endroit dans le code qui gaspille beaucoup de mémoire (bug), optfine pourra corriger les problèmes individuellement. Dans le cas contraire une grosse refonte interne du moteur jeu sera neccessaire, ce qui est une tache énorme non faisable par Optifine.
7 - Exemple
Voici un exemple de l'activité du GC, on y voit en particulier les piques de lag (en rouge sur la courbe):
- Le FPS moyen est de 50fps
- Le GC s'active toutes les 7 à 20 images
- Il y a entre 1 et 2 piques de lag chaque seconde, à cause du GC
TheMogMiner semble avoir été receptif à ces remarques très constructives, et à immédiatement demandé plus de détail à sp614x, lui demandant même ses coordonnées pour entrer en contact direct.
TheMogMiner déploire une mauvaise communication dans l'équipe de developpement chez Mojang:
"J'aurai pu dire que de nombreuses allocations de petits objets étaient une mauvaise chose, mais personne ne me l'a demandé"
"L'utilisation des BlockPos au lieu des triplés d'entiers me semble stupide, stupide, stuuuupide."
TheMogMiner ira jusqu'à se demander pourquoi sp614x n'a pas été recruté par Mojang: "Je ne vais pas prétendre savoir pourquoi nous n'avons pas recruté sp614x. Cela a eut lieu avant mon arrivé. Si j'avais le choix, j'aurai aimé qu'on le recrute lui aussi, parce qu'il serait interressant d'avoir une autre personne talentueuse avec qui travailler."
Espérons que ces conseils permettent aux développeurs de Mojang de corriger le tir, en réécrivant une nième fois le code de Minecraft.
On voit partout sur internet des méthodes de developpement à la mode (sp614x en citent quelques unes), malheureusement ils n'existent pas de réponse universelle a tout problème, ce n'est pas parce que une chose est a la mode, que tout le monde le dit, que c'est adapter a toutes les situations. Comme dit TheMogMiner: Pour une personne qui a un marteau, tous les problèmes ressemble à un clou.
Ici c'est pareil, ces jeunes developpeurs n'ont pas assez de recul et croit tout connaitre, ils ont lu ici et la sur internet que les immutables c'est bien, que l'allocation mémoire c'est bien, mais ils ont oublié qu'ils travaillaient sur une application temps-réel ou les contraites sont bien particulière.
D'ailleurs, de manière général, j'ai remarqué que toutes les méthodes de dev à la mode (design pattern, bibliothèque) sont très mauvaise pour les performances, c'est éxécrable, ça n'a comme but que de simplifier la vie des développeurs (et donc le temps de développement, et encore c'est pas toujours le cas).
Finallement Notch avant un gros defaut, un defaut avoué, il ne savait pas utiliser le multithreading.
La 1.8 corrigera ce manque, mais détruira toutes les optimisations que Notch maitrisé parfaitement, les optimisations dans la communication des données de rendu.
J'espère que Mojang arrivera a corriger tout cela.