Éviter la suppression du code inutile
Blackhole et état
Éviter la suppression du code inutile est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.
Éviter la suppression du code mort
Le piège le plus important des mesures de microperformances est la suppression du code mort (DCE) : si le compilateur à la volée prouve qu’un résultat n’est jamais utilisé, il supprime le calcul. Votre évaluation comparative ne mesure alors rien. JMH vous fournit deux outils pour empêcher cela : le renvoi des valeurs et le Blackhole.
Le piège du code mort
Cette boucle calcule une racine carrée un million de fois, mais n’utilise jamais le résultat. Un compilateur intelligent peut supprimer toute la boucle.
public class Main {
public static void main(String[] args) {
long t = System.nanoTime();
for (int i = 0; i < 1_000_000; i++) {
double ignored = Math.sqrt(i); // result thrown away
}
System.out.println("ns: " + (System.nanoTime() - t));
}
}Solution 1 : retourner le résultat
La défense la plus simple consiste à retourner la valeur calculée depuis la méthode @Benchmark. JMH consomme chaque valeur renvoyée, de sorte que la JVM ne peut pas prouver qu’elle est inutilisée.
import org.openjdk.jmh.annotations.Benchmark;
public class Bench {
@Benchmark
public double sqrt() {
return Math.sqrt(42.0); // returned -> consumed by JMH
}
}Solution 2 : le puits noir
Lorsqu’une évaluation comparative produit plusieurs valeurs ou que vous ne pouvez pas en retourner une, fournissez un Blackhole et appelez consume(...). Le puits noir convainc le compilateur à la volée que chaque valeur est utilisée, sans le coût d’un véritable traitement.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public void manyValues(Blackhole bh) {
for (int i = 0; i < 100; i++) {
bh.consume(Math.sqrt(i));
}
}
}Objets @State
Une classe @State contient des entrées opaques pour l’optimiseur, ce qui empêche l’évaluation des constantes. JMH l’instancie et la transmet à votre évaluation comparative. La portée peut être Thread, Benchmark (partagée) ou Group.
import org.openjdk.jmh.annotations.*;
public class Bench {
@State(Scope.Thread)
public static class Data {
public int x = 21;
}
@Benchmark
public int multiply(Data d) {
return d.x * 2; // d.x is not a compile-time constant
}
}@Setup et @TearDown
Dans une classe @State, les méthodes annotées avec @Setup s’exécutent avant la mesure et celles annotées avec @TearDown après. Le Level contrôle la fréquence : Trial (une fois), Iteration ou Invocation.
import org.openjdk.jmh.annotations.*;
@State(Scope.Thread)
public class Data {
int[] arr;
@Setup(Level.Trial)
public void init() {
arr = new int[1000];
for (int i = 0; i < arr.length; i++) arr[i] = i;
}
}Éviter les entrées constantes
Ne fournissez jamais de constantes littérales à la méthode testée. Math.sqrt(2.0) peut être réduite à une constante ; Math.sqrt(state.value) ne le peut pas. Récupérez toujours les entrées depuis un champ @State.
Retourner plusieurs valeurs
Si votre test de performance produit naturellement deux résultats, vous pouvez en retourner un et consommer l'autre via un Blackhole, ou les combiner. Laisser l'un ou l'autre sans consommation rouvre la faille liée à la DCE.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public int twoResults(Blackhole bh) {
int a = 3 * 7;
int b = 5 + 9;
bh.consume(b);
return a;
}
}Coût du Blackhole
Le Blackhole est conçu pour être extrêmement peu coûteux et résister lui-même aux optimisations, mais il n'est pas totalement gratuit. Pour les opérations ultrarapides, préférez retourner une seule valeur ; réservez Blackhole aux boucles et aux cas produisant plusieurs valeurs.
Vérifier la cohérence de vos chiffres
Si un test de performance indique un temps irréallement faible (inférieur à la nanoseconde pour un travail réel), suspectez la DCE ou l'évaluation des constantes. Vérifiez que les résultats sont retournés ou consommés et que les entrées proviennent de @State.
Mettre tout en pratique
Un test de performance robuste lit les entrées depuis un objet @State, effectue le travail, puis retourne le résultat ou le transmet à Blackhole.consume. Grâce à ces trois habitudes, la DCE et l'évaluation des constantes ne peuvent pas fausser vos mesures.
Vérification rapide
Vérifiez votre compréhension de la manière d'empêcher l'élimination du code mort.
Récapitulatif
Vous avez appris à garantir la fiabilité de vos tests de performance :
- L'élimination du code mort supprime les calculs inutilisés.
- Retournez un seul résultat afin que JMH le consomme.
- Utilisez Blackhole.consume pour les boucles et les valeurs multiples.
- Les objets @State rendent les entrées opaques et empêchent l'évaluation des constantes.
- @Setup / @TearDown préparent et nettoient l'état à un niveau choisi.
Questions Fréquemment Posées
La leçon « Éviter la suppression du code inutile » est-elle gratuite ?
Oui — le texte complet de « Éviter la suppression du code inutile » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Éviter la suppression du code inutile » ?
Blackhole et état Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Java Academy ?
Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Éviter la suppression du code inutile » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?
Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Pourquoi JMH
- Écrire une référence
- Préchauffage et itérations
- Éviter la suppression du code inutile