2014-05-07 22 views
5

Sto provando a convertire un po 'di codice Java2D in JavaFX e sono bloccato da un problema relativo alle prestazioni di JavaFX Canvas. Ad un certo punto, dovrò disegnare migliaia di piccoli cerchi sullo schermo.JavaFX Canvas delay

Il mio problema è che nel primo disegno, il mio codice impiega molto tempo per essere eseguito. Ma se devo eseguire un secondo disegno, ci vuole solo una frazione del tempo per disegnare (è almeno 10 volte più veloce).

C'è qualcosa che sto facendo male? C'è un modo per prevenire quel ritardo iniziale?

Ho scritto questo codice per testarlo. In questo codice disegno 500.000 cerchi in posizioni casuali su una tela 1000 x 1000 (creata in precedenza). Ho collegato questo codice a un evento click del pulsante e la prima volta che faccio clic ci vogliono 10 secondi per eseguirlo. Ma se clicco di nuovo, ci vogliono solo 0,025 secondi.

private void paintCanvas() { 
    long initTime = System.currentTimeMillis(); 

    GraphicsContext cg = canvas.getGraphicsContext2D(); 
    cg.setFill(Color.WHITE); 
    cg.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); 
    cg.setFill(Color.rgb(0, 0, 0, 0.1)); 

    Random rand = new Random(); 
    for (int i = 0; i < 500000; i++) {  
     cg.fillOval(1000 * rand.nextFloat(), 1000 * rand.nextFloat(), 2, 2); 
    } 

    long endTime = System.currentTimeMillis(); 
    System.out.println("Time spent on drawing:" + (endTime - initTime)/1000.0f);   
} 

In realtà non esiste un numero massimo di nuovi elementi. Può variare da alcune centinaia a centinaia di migliaia, a seconda delle esigenze degli utenti. E sì, va bene se alcuni elementi appaiono nel tempo.

+0

So che la 500.000 il valore è lì per dimostrare il problema, ma quanti nella tua applicazione di destinazione, qual è il numero massimo di * nuovi * elementi necessari per disegnare ogni fotogramma? In questo modo una risposta può essere meglio adattata ai tuoi vincoli specifici. Inoltre, è OK per l'app se alcuni elementi "pop-in" nel tempo? – jewelsea

+0

Ciao jewelsea. In realtà non esiste un numero massimo di nuovi elementi. Può variare da alcune centinaia a centinaia di migliaia, a seconda delle esigenze degli utenti. E sì, va bene se alcuni elementi appaiono nel tempo. –

+0

Riguarda [commento della mailing list dallo sviluppatore canvas] (http://mail.openjdk.java.net/pipermail/openjfx-dev/2014-May/013838.html). – jewelsea

risposta

1

Ragazzi, vi ringrazio per l'aiuto. Ho inviato la stessa domanda alla mailing list di OpenJFX e uno degli sviluppatori ha risposto. Sembra che la mia versione di JavaFX 2.2 usi ancora un vecchio modello per far crescere il buffer dei comandi. La nuova versione, JavaFX 8, utilizza un modello più efficiente che rende il primo dipinto veloce come i successivi.

Ecco la risposta che ho ricevuto:

Jim Graham (james.graham a Oracle.com)

lun 12 mag 21:17:19 UTC 2014

Ciò è probabilmente dovuto alla crescente buffer dei comandi che è stato fatto linearmente ad un certo punto (probabilmente ancora fatto in quel modo in 2.2), ma è ora esponenziale in 8.0. Il tempo prima di rendering è quasi istantanea in 8.0, ma richiede molto tempo come l'avete trovato quando provo con una mia vecchia 2.x costruisce ...

 ...jim 
0

mi viene in mente un paio di cose, ma cominciamo con un:

potrebbe essere che la JVM Just in Time compilatore sta colpendo tua esecuzione. Dipende dall'opzione JVM (se si tratta di JIT client o server e se si sta utilizzando AggresiveOpts o meno).

Ricordare che la JVM è abbastanza intelligente da eseguire ottimizzazioni su quel loop. Secondo me puoi iniziare da lì, metterlo sulle tue opzioni JVM quando esegui questo: -XX: + PrintCompilation, e guarda l'output su console, il tuo metodo dovrebbe essere compilato durante la prima esecuzione e quindi non dovresti osservare alcuna compilation durante il secondo. Se è così, allora sai che questo codice è stato compilato e memorizzato nel CodeCache, e l'esecuzione non avviene attraverso l'interprete ma attraverso un codice compilato in modo nativo, che avrà prestazioni migliori.

Fateci sapere le vostre scoperte!

opzioni JVM di riferimento (potrebbe aver bisogno di trovare il vostro specifico documento JVM): http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

P.S. puoi provare a ridurre l'orario di inizio prima di istanziare a caso ?, sarebbe bello essere in grado di prendere due volte, una all'inizio e subito prima della casualità, e la seconda, subito dopo quest'ultima ed infine quando la il ciclo è terminato, l'idea è di provare a capire dove il codice sta spendendo il suo tempo quando si osserva questo (il ciclo o l'istanza della tela).