2009-12-04 13 views
0
for n in `cd src; find . -name "*.java"; cd -`; 
    do a=`echo $n | cut -d '.' -f2`; 
    if [[ src/$a.java -nt build/$a.class ]]; 
    then echo src/$a.java; 
    fi; 
done 

Il répertorie tous les fichiers Java dans l'arborescence src; puis pour chacun d'eux, il supprime le suffixe « .java » (cut -d '.' -f2 parce find . sortie est préfixé avec .). Il utilise ensuite -nt pour tester si le fichier java dans l'arborescence src est plus récent que le fichier de classe correspondant dans l'arbre de construction; s'il est plus récent, il est sorti. [javac peut alors utiliser ceci pour compiler seulement les fichiers src nécessaires, au lieu d'utiliser ant ou make]Comment cette comparaison entre src et build tree timestamp peut-elle être plus rapide?

Le problème est qu'il est trop lent, prenant environ 275ms. Comment faire plus vite?

Ou est-il un moyen plus rapide de le faire en bash? Je ne vois pas comment le faire avec find, diff, ni rsyncmake (qui ne semble pas traverser les arbres automatiquement, et les besoins des fichiers source répertoriés explicitement).

Répondre

1

essayez ceci:

for f in src/*.java; do 
    file=`basename $f`; 
    if [[ src/$file -nt build/${file//.java/} ]]; then 
    echo src/$file; 
    fi; 
done 
+0

Cela ne traitera pas récursivement les sous-répertoires de src. –

+0

Je pense que vous voulez dire $ {fichier/.java/.class} dans la substitution? –

+0

Merci, j'aime le 'basename $ f' et' $ {fichier // .java /} '- je ne les connaissais pas! Dans ce dernier, je pense que vous vouliez dire 'build/$ {file/.java/.class}'. Mais 'src/* .java' et' basename' ne couvrent qu'un niveau, pas un arbre src (par exemple des paquets imbriqués). – 13ren

0

Adopter l'approche de kon au nom du fichier munging, la vitesse améliore de 320ms à 45ms en moyenne. Merci, kon!

for n in `cd src; find . -name "*.java"; cd -`; do 
    if [[ src/$n -nt build/${n/.java/.class} ]]; 
    then echo src/$n; 
    fi; 
done 

L'original est un peu plus lent maintenant (était 275ms, maintenant 320ms); Je ne sais pas pourquoi. J'utilise la même ligne. Peut-être différentes sources du système après avoir joué une vidéo.

EDIT re commentaire de première: le mutiler "src /" loin au lieu de cd src; ... cd -;. Notez que les deux $n et $n2 sont utilisés [vous ne pouvez pas imbriquer le $ {var/A/B} construire, pouvez-vous?]

for n in `find src -name "*.java"`; do 
    n2=${n/src/} 
    if [[ $n -nt build/${n2/.java/.class} ]]; 
    then echo $n; 
    fi; 
done 
+0

Je ne pense pas que le '; cd -' est nécessaire ici. – rsp

+0

@rsp Je suis d'accord. Le '; cd -' renverse le 'cd src;', qui était nécessaire pour que le même fragment de chemin apparaisse dans les arbres src et build. Je vais mettre à jour cette réponse avec le nom mangling à la place. – 13ren

+1

La raison de la '; cd -' n'est pas nécessaire est que le 'cd src; find ... 'sont exécutées dans un sous-shell. Quand cela se termine, vous êtes toujours dans le parent de 'src'. –

0
ant

réalise la logique de construction intelligente, il ne construira pas une classe à moins que la la source a été modifiée. Vous pouvez également vous intéresser à Scons, qui n'est pas un outil de compilation Java natif, mais qui est très pratique pour compiler des arborescences de construction complexes et efficaces et dispose également de Java Builder.

+0

J'avais l'habitude d'utiliser fourmi, mais c'est trop lent. J'ai piraté mon propre outil de construction, qui réduit le temps de compilation de 5000ms à 250ms (en moyenne). Cette question concerne un raffinement qui ne devrait ajouter que quelques ms à cela. Je viens de regarder scons, mais il n'y a pas de chiffres de performance dans la faq. Je vais garder un œil dessus cependant; Merci. – 13ren

+0

J'ai juste essayé scons; il génère des commandes javac, ce qui n'est pas ce dont j'ai besoin. De plus, j'ai eu beaucoup de mal à le configurer: les exemples du manuel et 'man scons' ne fonctionnent pas tels quels, et à la fin il n'a pas pu trouver javac à compiler. Même si j'ai configuré l'environnement avec l'outil 'javac' et transmis dans la variable d'environnement JAVA_HOME. Je le mentionne parce que je suppose qu'il ne sert pas à grand chose en tant qu'outil Java, en considérant ant, IDE et il est écrit en python. Finalement, le run le plus rapide que j'ai eu a été de 1121ms (qui génère la commande javac, pas l'exécuter). Plus rapide que la fourmi, mais pas pour moi. – 13ren

1

Je ne sais pas si cette structure serait plus vite, mais il est peut-être la peine d'essayer:

while read n 
do 
    # capture the basename all at once 
    [[ $n =~ src/(.*)\.java ]] # escape the parentheses for Bash < 3.2 (or thereabouts) 
    [[ $n -nt "build/${BASH_REMATCH[1]}.class" ]] && echo $n 
done < <(find src -name "*.java") 

Le formulaire while ne sera probablement pas fournir tout coup de pouce. L'effondrement if peut. L'expression régulière peut fournir une petite contribution.

Comme vous l'avez découvert, éliminer un appel à cut a fait la plus grande différence.

+0

merci, bien que j'obtiens une erreur de syntaxe près de 'src/(. ''. – 13ren

+0

quelle version bash utilisez-vous? Peut-être qu'il ne supporte pas l'opérateur binaire = ~ – kon

+0

'= ~' a été introduit en 3.0 et là étaient des changements qui affectent la compatibilité quelque part autour de 3.1 ou 3.2 –