Ho qualche problema con un gioco sviluppato in Java, che è piuttosto lento. L'ho confrontato un po 'e ho trovato il problema: la maggior parte delle volte la JVM si trova nella Object.<init>()
poiché c'è un lotto di oggetti che viene creato e distrutto ogni tick.
Questa classe che viene creata spesso è una classe molto piccola, solo 3 numeri interi, niente di più. Ma questo era un problema che ho cercato di risolvere. Così ho iniziato alcuni test su come avrei potuto aumentare la velocità. Quello che ho trovato è inaspettato. Prima di tutto, il codice che ho provato è come follwos:
public class NewVsCloneTest implements Cloneable {
int a = 0;
int b = 0;
int c = 0;
public static void main(String... args) throws Exception {
Stack h = new Stack();
System.out.println("Benchmarking Copy vs Clone...");
long time = 0;
long n = 0, c = 0, s = 0;
NewVsCloneTest obj = null;
for(int num = 0; num < 50; num++){
time = System.currentTimeMillis();
for(int i = 0; i < 10000000; i++){
obj = new NewVsCloneTest();
}
n += (System.currentTimeMillis() - time);
System.out.println("New took " + (System.currentTimeMillis() - time) + " MilliSeconds");
time = System.currentTimeMillis();
for(int i = 0; i < 10000000; i++){
obj = (NewVsCloneTest) obj.clone();
}
c += (System.currentTimeMillis() - time);
System.out.println("Clo took " + (System.currentTimeMillis() - time) + " MilliSeconds");
time = System.currentTimeMillis();
for(int i = 0; i < 10000000; i++){
obj = h.getOne();
h.pushOne(obj);
}
s += (System.currentTimeMillis() - time);
System.out.println("Sta took " + (System.currentTimeMillis() - time) + " MilliSeconds");
}
System.out.println("After 50 runs, new took " + n + ", clone took " + c + " and stack took " + s);
System.out.println("On average, new took " + n / 50.0 + ", clone took " + c / 50.0 + " and stack took " + s / 50.0 + " per 10 mio runs.");
}
public static class Stack {
private NewVsCloneTest[] vars = new NewVsCloneTest[10];
{
for(int i = 0; i < 10; i++)
vars[i] = new NewVsCloneTest();
}
int pos = 9;
public NewVsCloneTest getOne(){
return vars[pos--];
}
public void pushOne(NewVsCloneTest var){
vars[++pos] = var;
}
}
}
I risultati che ottengo:
After 50 runs, new took 3462, clone took 5784 and stack took 4132
On average, new took 69.24, clone took 115.68 and stack took 82.64 per 10 mio runs.
Quindi, questo è stato davvero inaspettato per me, che il nuovo è più veloce della piccola implementazione dello stack. Voglio dire, lo stack non può fare altro che prenderne e metterne uno. Niente rangechecks, niente cambi di taglia, solo niente. Ho persino dato "NewVsCloneTests" a qualche altro in più, alcuni long, alcuni oggetti (solo nullptr) e alcuni caratteri, ma ho ottenuto lo stesso risultato.
Quindi il fatto è che ho visto un sacco di codice sorgente in cui sono memorizzate istanze di classi memorizzate nella cache molto spesso ma solo per un breve periodo, quindi ho pensato che avrebbe differenza. Ma i miei risultati mi mostrano che anche peggio .
Come posso gestire questo particolare problema?
La classe che viene istanziata spesso è solo un dataholder per le coordinate (x, y, z), e viene istanziata spesso (copiata, se lo si vuole) perché non posso distribuire i miei originali.