Il seguente misura di codice il tempo necessario per 100 invocazioni del metodo maniglia (Object o) dall'interfaccia Handler (Sì, è la profilazione di cattiva qualità):Java - ListaLinkata - Prestazioni diminuisce con il numero di classi differenti in esso
package test;
import java.util.LinkedList;
public class Test {
static int i = 0;
private interface Handler {
public void handle(Object o);
}
private static class SuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class NoSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LulSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LilSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LolSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LalSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LylSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
private static class LzlSuperHandler implements Handler {
public void handle(Object o) { i += 1; }
}
public static void main(String[] args) {
LinkedList<Handler> ll = new LinkedList<Handler>();
for(int j = 0; j < 100; j++) {
if((j % 8) == 0) ll.add(new SuperHandler());
if((j % 8) == 1) ll.add(new NoSuperHandler());
if((j % 8) == 2) ll.add(new LulSuperHandler());
if((j % 8) == 3) ll.add(new LilSuperHandler());
if((j % 8) == 4) ll.add(new LolSuperHandler());
if((j % 8) == 5) ll.add(new LalSuperHandler());
if((j % 8) == 6) ll.add(new LylSuperHandler());
if((j % 8) == 7) ll.add(new LzlSuperHandler());
}
long begin = System.currentTimeMillis();
for(int j = 0; j < 1000000; j++) for(Handler h: ll) h.handle(null);
System.out.println("time in ms: " + (System.currentTimeMillis() - begin));
System.out.println("i: " + i);
}
}
il fatto è che se il ListaLinkata contiene un solo tipo di Handler, per esempio SuperHandler, il tempo di esecuzione è inferiore se fossero 2, 3, ecc differe nt tipi di Handler. E ogni volta che aggiungo un nuovo tipo di gestore nell'elenco, le prestazioni diminuiscono.
Per esempio quando cambio solo questa parte ricevo prestazioni migliori rispetto a sopra:
for(int j = 0; j < 100; j++) {
if((j % 2) == 0) ll.add(new SuperHandler());
if((j % 2) == 1) ll.add(new NoSuperHandler());
}
c'è un'ottimizzazione speciale che opera qui? Cosa nell'architettura JAVA diminuisce le prestazioni? Il mio test è sbagliato perché il gestore non utilizzato viene "rimosso" o "nascosto" dal compilatore? (Sto usando Linux Ubuntu - JAVA 1.7, da Oracle)
AFAIK, il limite per i metodi virtuali inline è 2 in HotSpot. Non sono sicuro che il solo caricamento delle classi sia sufficiente per innescare una de-ottimizzazione. –
@PeterLawrey: Ah - grazie per il chiarimento extra. Modificherà. –
Vedere la mia risposta per un esempio. Ho la stessa lista in cui 8 tipi diversi sono chiamati in un posto e un altro in cui sono allineate 8 chiamate diverse per chiamare solo un tipo (ma dalla stessa lista) La differenza di prestazioni è drammatica. –