Je suis nouveau sur Java, et j'utilisais du code hier soir, et cela m'a vraiment dérangé. Je construisais un programme simple pour afficher toutes les sorties X dans une boucle for, et j'ai remarqué une diminution MASSIVE des performances, lorsque j'ai utilisé le module comme variable % variable
vs variable % 5000
ou autre chose. Quelqu'un peut-il m'expliquer pourquoi et quelle en est la cause? Alors je peux être meilleur ...
Voici le code "efficace" (désolé si je me trompe un peu de syntaxe, je ne suis pas sur l'ordinateur avec le code en ce moment)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
Voici le "code inefficace"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
Remarquez que j'avais une variable de date pour mesurer les différences, et une fois qu'elle est devenue assez longue, la première a pris 50 ms tandis que l'autre a pris 12 secondes ou quelque chose comme ça. Vous devrez peut-être augmenter lestopNum
ou diminuer le progressCheck
si votre PC est plus efficace que le mien ou autre.
J'ai cherché cette question sur le Web, mais je ne trouve pas de réponse, peut-être que je ne la pose pas correctement.
EDIT: Je ne m'attendais pas à ce que ma question soit si populaire, j'apprécie toutes les réponses. J'ai effectué un benchmark sur chaque mi-temps, et le code inefficace a pris beaucoup plus de temps, 1/4 de seconde contre 10 secondes à peu près. Certes, ils utilisent println, mais ils font tous les deux le même montant, donc je n'imagine pas que cela fausserait beaucoup, d'autant plus que l'écart est répétable. En ce qui concerne les réponses, comme je suis nouveau sur Java, je vais laisser les votes décider pour l'instant quelle réponse est la meilleure. J'essaierai d'en choisir un d'ici mercredi.
EDIT2: Je vais faire un autre test ce soir, où au lieu de module, il incrémente simplement une variable, et quand il atteindra progressCheck, il en effectuera un, puis remettra cette variable à 0. pour une troisième option.
EDIT3.5:
J'ai utilisé ce code, et ci-dessous je vais montrer mes résultats .. Merci à TOUS pour la merveilleuse aide! J'ai également essayé de comparer la valeur courte du long à 0, de sorte que tous mes nouveaux contrôles se produisent jamais "65536" fois, ce qui le rend égal en répétitions.
public class Main {
public static void main(String[] args) {
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 65536;
final long finalProgressCheck = 50000;
long date;
// using a fixed value
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if (i % 65536 == 0) {
System.out.println(i);
}
}
long final1 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
//using a variable
for (long i = startNum; i <= stopNum; i++) {
if (i % progressCheck == 0) {
System.out.println(i);
}
}
long final2 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using a final declared variable
for (long i = startNum; i <= stopNum; i++) {
if (i % finalProgressCheck == 0) {
System.out.println(i);
}
}
long final3 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using increments to determine progressCheck
int increment = 0;
for (long i = startNum; i <= stopNum; i++) {
if (increment == 65536) {
System.out.println(i);
increment = 0;
}
increment++;
}
//using a short conversion
long final4 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if ((short)i == 0) {
System.out.println(i);
}
}
long final5 = System.currentTimeMillis() - date;
System.out.println(
"\nfixed = " + final1 + " ms " + "\nvariable = " + final2 + " ms " + "\nfinal variable = " + final3 + " ms " + "\nincrement = " + final4 + " ms" + "\nShort Conversion = " + final5 + " ms");
}
}
Résultats:
- fixe = 874 ms (normalement autour de 1000 ms, mais plus rapide car il s'agit d'une puissance de 2)
- variable = 8590 ms
- variable finale = 1944 ms (était ~ 1000 ms lors de l'utilisation de 50000)
- incrément = 1904 ms
- Conversion courte = 679 ms
Pas assez surprenant, faute de division, la conversion courte était 23% plus rapide que la méthode «rapide». Ceci est intéressant à noter. Si vous avez besoin de montrer ou de comparer quelque chose toutes les 256 fois (ou environ), vous pouvez le faire et utiliser
if ((byte)integer == 0) {'Perform progress check code here'}
UNE FINALE NOTE INTÉRESSANTE, en utilisant le module sur la «Variable déclarée finale» avec 65536 (pas un joli nombre) était la moitié de la vitesse de (plus lente) que la valeur fixe. Là où auparavant, il était comparé à la même vitesse.
final
devant laprogressCheck
variable, les deux fonctionnent à nouveau à la même vitesse. Cela me porte à croire que le compilateur ou le JIT parvient à optimiser la boucle lorsqu'il sait queprogressCheck
c'est constant.