How can this src vs. build tree timestamp comparison be faster?
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
It lists all the java files in the src tree; then for each one, it removes the suffix ".java" (cut -d '.' -f2
because find .
output is prefixed with .
). It then uses -nt
to test if the java file in the src tree is newer than the corresponding class file in the build tree; if it is newer, it is output. [javac can then use this to compile only the needed src files, instead of using ant
or make
]
The problem is that it is too slow, taking about 275ms. How to make it faster?
Or is there a faste开发者_如何转开发r way to do this in bash? I can't see how to do it with find
, diff
, rsync
nor make
(which doesn't seem to traverse trees automatically, and needs explicitly listed source files).
try this:
for f in src/*.java; do
file=`basename $f`;
if [[ src/$file -nt build/${file//.java/} ]]; then
echo src/$file;
fi;
done
I don't know if this structure would be any faster, but it might be worth a try:
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")
The while
form probably won't provide any boost. The collapsed if
may. The regex might provide a small contribution.
As you've found out, eliminating a call to cut
has made the biggest difference.
ant performs smart building logic, it will not build a class unless the source was modified.
You might also like to look into scons which is not a native Java build tool but is very handy at compiling efficient complex build trees and does have java builder as well.
Adopting kon's approach to the filename munging, the speed improves from 320ms to 45ms on average. Thanks 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
The original is a bit slower now (was 275ms; now 320ms); I don't know why. I'm using the same line. Maybe different system sources after playing a video.
EDIT re rst's comment: mangling the "src/" away instead of cd src;
... cd -;
. Note that both $n
and $n2
are used [you can't nest the ${var/A/B} construct, can you?]
for n in `find src -name "*.java"`; do
n2=${n/src/}
if [[ $n -nt build/${n2/.java/.class} ]];
then echo $n;
fi;
done
精彩评论