2013-03-03 1 views
1

J'utilise ce petit morceau de code pour tester quelle méthode est plus rapide:Grande différence sur System.currentTimeMillis()

public void test() { 
    long start = System.currentTimeMillis(); 
    MyDate date = new MyDate(); 
    int max = 5000; 

    for (int i = 0; i < max; i++) { 
    Calendar.getInstance().getTimeInMillis(); // <-- 
    } 

    System.out.println("Calendar instance delay: " + (System.currentTimeMillis() - start)); 
    start = System.currentTimeMillis(); 

    for (int i = 0; i < max; i++) { 
    date.getMillis(); // <-- 
    } 

    System.out.println("My date delay: " + (System.currentTimeMillis() - start)); 
} 

Donc, au fond, je suis essayer de comparer les performances entre Calendar.getInstance().getTimeInMillis() et MyDate.getMillis() (MyDate est une classe créée par moi).

Eh bien, quand je courais le code ci-dessus, la sortie était:

Calendar instance delay: 413 
My date delay: 2 

MAIS, quand j'inversé l'ordre (d'abord appelé MaDate, et après le calendrier), je me suis:

My date delay: 247 
Calendar instance delay: 119 

J'ai essayé d'utiliser System.nanoTime(), mais la même chose s'est produite: le premier code à tester est celui qui a pris le plus de temps.

Quelqu'un sait pourquoi cette différence se produit? Ou, existe-t-il un moyen de profiler les codes avec précision sans utiliser une application de profileur externe (juste du code Java pur)?

Merci.

+0

Eh bien d'abord, vous initialisez l'objet date dans le premier bloc de synchronisation. Deuxièmement, vous pourriez frapper GC - 5000 n'est probablement pas assez d'appels. Enfin, est-ce vraiment un problème de performance dans votre application? –

+0

Quelle est votre objection contre l'utilisation d'un profileur? – Torious

+0

@PhilipWhitehouse Non, je l'utilise juste à des fins de test. – BloodShura

Répondre

4

Pour tester la performance du "petit" code, vous devez l'appeler plusieurs fois. Sinon, les effets du JIT, de la mise en cache et de la prédiction de branchement gâchent vos tests. Si je vous appelle au téléphone pour voir combien de temps cela prendra avant de répondre, j'obtiendrai une réponse très différente si je vous ai appelé il y a quelques secondes.

+0

Merci, David! – BloodShura

+0

+1 En résumé, vous devez ignorer les résultats des 10 000 premières itérations. La réponse est que System.currentTimeMillis() est le plus rapide car lorsque vous lisez le code, vous pouvez voir tous les autres appels et faire un peu plus de travail. –

1

Il est classe dans StopWatch communes lang qui utilise System.nanoTime,

http://commons.apache.org/lang/

org.apache.commons.lang.time.StopWatch

+0

Merci! Je vais jeter un coup d'oeil là-dessus. – BloodShura

1

Lors de la mesure des performances, gardez à l'esprit que la la JVM peut éliminer le code qui n'a aucun effet secondaire dans le cadre de l'optimisation.

Pour éviter cela, vous pouvez faire ce qui suit:

for (int i = 0; i < max; i++) { 
    long a = date.getMillis(); 
    if (a % 1000 == i) { 
     System.out.print(a); 
    } 
} 

Une autre chose à prendre en compte est le point d'accès d'optimisation. Vous devriez "réchauffer" votre code avant de mesurer.

+0

Merci, mbelow! – BloodShura

Questions connexes