2016-04-11 34 views
9

Occasionalmente una leggera modifica a un file di origine Java come alcuni cast espliciti aggiuntivi per aiutare il compilatore a migliorare il tempo di compilazione da 4 minuti a 3 secondi per un singolo file java (Soprattutto in Java 8).Timing per quanto tempo ciascun file impiega per compilare con ant

Il problema è: in un grande progetto java, come si trova quali particolari file .java vengono compilati lentamente?

C'è un modo per convincere Ant a calcolare quanto tempo ci vuole per compilare ogni file .java?

+0

In teoria si potrebbe probabilmente farlo con un obiettivo Ant personalizzato usando JSR 199 (API del compilatore Java) per richiamare il compilatore, ma sembra molto lavoro. Potresti solo guardare i timestamp dei file .class? – Pace

+0

Possibilmente. Quindi basta controllare i delta tra le date di modifica ?. Mi chiedo se il comando javac possa essere avvolto in un file batch che richiede quanto tempo ci vuole per eseguire. Quindi devi solo fare uso di qualcos'altro piuttosto che javac. – clinux

+4

Il problema è che javac non viene chiamato un file alla volta.javac non è un compilatore incrementale e quindi deve contenere ogni file nello stesso momento. Quindi, la tempistica di quanto dura javac non è molto diversa dalla temporizzazione dell'intera compilazione. – Pace

risposta

3

Penso che questo potrebbe essere possibile. Ecco cosa ho trovato:

Se si utilizza Java 8, è possibile registrare un Plugin con il compilatore per aggiungere alcune funzionalità aggiuntive durante la compilazione. La documentazione ha questo da dire circa i plugin:

Si prevede che un tipico plug-in semplicemente registrare un TaskListener per essere informato degli eventi durante l'esecuzione della compilazione, e che il resto del lavoro sarà fatto dal listener del compito.

Quindi è possibile impostare un plug-in per utilizzare un TaskListener e disporre dei timestamp del log del listener dell'attività quando viene generata la classe.

package xyz; 
import com.sun.source.util.JavacTask; 
import com.sun.source.util.Plugin; 

public class TimestampPlugin implements Plugin { 


    @Override 
    public String getName() { 
     return "Timestamp_Plugin"; 
    } 

    @Override 
    public void init(JavacTask task, String... strings) { 
     task.setTaskListener(new FileTimestampListener()); 
    } 
} 

Documentation for TaskListener. Un listener di attività viene passato a TaskEvent, che ha un Kind. Nel tuo caso sembra che ti interessi la generazione.

package xyz; 
import com.sun.source.util.TaskEvent; 
import com.sun.source.util.TaskListener; 

import java.util.HashMap; 

public class FileTimestampListener implements TaskListener { 
    HashMap<String, Long> timeStampMap = new HashMap<>(); 

    @Override 
    public void started(TaskEvent taskEvent) { 
     if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) { 
      String name = taskEvent.getSourceFile().getName(); 
      timeStampMap.put(name, System.currentTimeMillis()); 
     } 
    } 

    @Override 
    public void finished(TaskEvent taskEvent) { 
     if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) { 
      String name = taskEvent.getSourceFile().getName(); 
      System.out.println("Generated " + name + " over " + (System.currentTimeMillis() - timeStampMap.get(name)) + " milliseconds"); 
     } 
    } 
} 

Questo è un esempio semplice, ma dovrebbe essere semplice da qui a creare qualcosa di simile a un file di registro per memorizzare le informazioni raccolte. Come puoi vedere nella funzione init del plugin, gli argomenti possono essere passati al plugin dalla riga di comando.

Il plug-in viene configurato specificandolo con l'argomento del compilatore -Xplugin. Non sono sicuro del perché, ma non sembra esserci alcuna documentazione su this page, ma può essere utilizzato impostando un file chiamato com.sun.source.util.Plugin (il nome della classe FQ dell'interfaccia da implementare) nella directory META-INF/services. Quindi:

META-INF 
|-- services 
    |-- com.sun.source.util.Plugin 

E in tale elenco di file il nome della classe FQ dell'implementazione di questa classe. Quindi il contenuto del file sarebbero:

xyz.TimestampPlugin 

nel vostro compito Ant ti basta specificare un flag di compilazione -Xplugin: Timestamp_Plugin (notare che questo è il nome fornito dal plugin del getName() la funzione). È inoltre necessario fornire le dipendenze del plug-in e del runtime compilate sul classpath o sul percorso del processore di annotazione, se ne viene specificato uno.

Problemi correlati