Author: jglick Date: Wed Oct 3 16:44:10 2007 New Revision: 581748 URL: http://svn.apache.org/viewvc?rev=581748&view=rev Log: Various microoptimizations to reduce I/O load of common tasks, esp. no-op <javac> and <depend>. Many inner loops altered to make just 1-2 system calls rather than 4-5. You can easily see how wasteful the previous code was, and find the culprits, by patching r/o java.io.File methods and adding to -Xbootclasspath/p (or use AspectJ). E.g.:
public boolean isDirectory() { System.err.println("isDirectory: " + this); if (Math.random() < .01) Thread.dumpStack(); // as before... } Ant still makes an order of magnitude more system calls to do what seem like simple operations than you would think necessary, but this patch should at least improve the situation. Modified: ant/core/trunk/WHATSNEW ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Rmic.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java ant/core/trunk/src/main/org/apache/tools/ant/util/SourceFileScanner.java Modified: ant/core/trunk/WHATSNEW URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/WHATSNEW (original) +++ ant/core/trunk/WHATSNEW Wed Oct 3 16:44:10 2007 @@ -196,6 +196,10 @@ Other changes: -------------- + +* Various small optimizations speed up common tasks such as <javac> on large + filesets, reducing both I/O and CPU usage. + * Profiling logger has been added with basic profiling capabilities. * <script> now has basic support for JavaFX scripts Modified: ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java Wed Oct 3 16:44:10 2007 @@ -1065,28 +1065,25 @@ protected void scandir(File dir, String vpath, boolean fast) { if (dir == null) { throw new BuildException("dir must not be null."); - } else if (!dir.exists()) { - throw new BuildException(dir + " doesn't exist."); - } else if (!dir.isDirectory()) { - throw new BuildException(dir + " is not a directory."); } + String[] newfiles = dir.list(); + if (newfiles == null) { + if (!dir.exists()) { + throw new BuildException(dir + " doesn't exist."); + } else if (!dir.isDirectory()) { + throw new BuildException(dir + " is not a directory."); + } else { + throw new BuildException("IO error scanning directory '" + + dir.getAbsolutePath() + "'"); + } + } + scandir(dir, vpath, fast, newfiles); + } + private void scandir(File dir, String vpath, boolean fast, String[] newfiles) { // avoid double scanning of directories, can only happen in fast mode if (fast && hasBeenScanned(vpath)) { return; } - String[] newfiles = dir.list(); - - if (newfiles == null) { - /* - * two reasons are mentioned in the API docs for File.list - * (1) dir is not a directory. This is impossible as - * we wouldn't get here in this case. - * (2) an IO error occurred (why doesn't it throw an exception - * then???) - */ - throw new BuildException("IO error scanning directory '" - + dir.getAbsolutePath() + "'"); - } if (!followSymlinks) { Vector noLinks = new Vector(); for (int i = 0; i < newfiles.length; i++) { @@ -1112,25 +1109,26 @@ for (int i = 0; i < newfiles.length; i++) { String name = vpath + newfiles[i]; File file = new File(dir, newfiles[i]); - if (file.isDirectory()) { + String[] children = file.list(); + if (children == null) { // probably file if (isIncluded(name)) { - accountForIncludedDir(name, file, fast); + accountForIncludedFile(name, file); + } else { + everythingIncluded = false; + filesNotIncluded.addElement(name); + } + } else { // dir + if (isIncluded(name)) { + accountForIncludedDir(name, file, fast, children); } else { everythingIncluded = false; dirsNotIncluded.addElement(name); if (fast && couldHoldIncluded(name)) { - scandir(file, name + File.separator, fast); + scandir(file, name + File.separator, fast, children); } } if (!fast) { - scandir(file, name + File.separator, fast); - } - } else if (file.isFile()) { - if (isIncluded(name)) { - accountForIncludedFile(name, file); - } else { - everythingIncluded = false; - filesNotIncluded.addElement(name); + scandir(file, name + File.separator, fast, children); } } } @@ -1156,6 +1154,12 @@ processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected); if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) { scandir(file, name + File.separator, fast); + } + } + private void accountForIncludedDir(String name, File file, boolean fast, String[] children) { + processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected); + if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) { + scandir(file, name + File.separator, fast, children); } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Rmic.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Rmic.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Rmic.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/Rmic.java Wed Oct 3 16:44:10 2007 @@ -524,9 +524,15 @@ scanDir(baseDir, files, adapter.getMapper()); } else { // otherwise perform a timestamp comparison - at least - scanDir(baseDir, new String[] { - classname.replace('.', File.separatorChar) - + ".class" }, adapter.getMapper()); + String path = classname.replace('.', File.separatorChar) + ".class"; + File f = new File(baseDir, path); + if (f.isFile()) { + scanDir(baseDir, new String[] { path }, adapter.getMapper()); + } else { + // Does not exist, so checking whether it is up to date makes no sense. + // Compilation will fail later anyway, but tests expect a certain output. + compileList.add(classname); + } } int fileCount = compileList.size(); if (fileCount > 0) { Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/depend/Depend.java Wed Oct 3 16:44:10 2007 @@ -773,18 +773,21 @@ * Find the source file for a given class * * @param classname the classname in slash format. + * @param sourceFileKnownToExist if not null, a file already known to exist (saves call to .exists()) */ - private File findSourceFile(String classname) { - String sourceFilename = classname + ".java"; + private File findSourceFile(String classname, File sourceFileKnownToExist) { + String sourceFilename; int innerIndex = classname.indexOf("$"); if (innerIndex != -1) { sourceFilename = classname.substring(0, innerIndex) + ".java"; + } else { + sourceFilename = classname + ".java"; } // search the various source path entries for (int i = 0; i < srcPathList.length; ++i) { File sourceFile = new File(srcPathList[i], sourceFilename); - if (sourceFile.exists()) { + if (sourceFile.equals(sourceFileKnownToExist) || sourceFile.exists()) { return sourceFile; } } @@ -812,11 +815,10 @@ int length = filesInDir.length; int rootLength = root.getPath().length(); + File sourceFileKnownToExist = null; // speed optimization for (int i = 0; i < length; ++i) { File file = new File(dir, filesInDir[i]); - if (file.isDirectory()) { - addClassFiles(classFileList, file, root); - } else if (file.getName().endsWith(".class")) { + if (filesInDir[i].endsWith(".class")) { ClassFileInfo info = new ClassFileInfo(); info.absoluteFile = file; String relativeName = file.getPath().substring( @@ -824,8 +826,10 @@ file.getPath().length() - ".class".length()); info.className = ClassFileUtils.convertSlashName(relativeName); - info.sourceFile = findSourceFile(relativeName); + info.sourceFile = sourceFileKnownToExist = findSourceFile(relativeName, sourceFileKnownToExist); classFileList.addElement(info); + } else { + addClassFiles(classFileList, file, root); } } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java Wed Oct 3 16:44:10 2007 @@ -615,16 +615,16 @@ */ public static boolean isOutOfDate(Resource src, Resource target, long granularity) { - if (!src.isExists()) { + long sourceLastModified = src.getLastModified(); + if (sourceLastModified == 0L) { + // Does not exist. Quicker than checking exists() again. return false; } - if (!target.isExists()) { + long targetLastModified = target.getLastModified(); + if (targetLastModified == 0L) { return true; } - if ((src.getLastModified() - granularity) > target.getLastModified()) { - return true; - } - return false; + return (sourceLastModified - granularity) > targetLastModified; } /** Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/util/ResourceUtils.java Wed Oct 3 16:44:10 2007 @@ -61,17 +61,6 @@ */ public class ResourceUtils { - private static final class Outdated implements ResourceSelector { - private Resource control; - private long granularity; - private Outdated(Resource control, long granularity) { - this.control = control; - this.granularity = granularity; - } - public boolean isSelected(Resource r) { - return SelectorUtils.isOutOfDate(control, r, granularity); - } - } /** Utilities used for file operations */ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); @@ -144,7 +133,7 @@ ResourceCollection source, FileNameMapper mapper, ResourceFactory targets, - long granularity) { + final long granularity) { if (source.size() == 0) { logTo.log("No sources found.", Project.MSG_VERBOSE); return Resources.NONE; @@ -154,7 +143,7 @@ Union result = new Union(); for (Iterator iter = source.iterator(); iter.hasNext();) { - Resource sr = (Resource) iter.next(); + final Resource sr = (Resource) iter.next(); String srName = sr.getName(); srName = srName == null ? srName : srName.replace('/', File.separatorChar); @@ -178,8 +167,16 @@ } //find the out-of-date targets: Restrict r = new Restrict(); - r.add(new And(new ResourceSelector[] {Type.FILE, new Or( - new ResourceSelector[] {NOT_EXISTS, new Outdated(sr, granularity)})})); + r.add(new ResourceSelector() { + public boolean isSelected(Resource target) { + /* Extra I/O, probably wasted: + if (target.isDirectory()) { + return false; + } + */ + return SelectorUtils.isOutOfDate(sr, target, granularity); + } + }); r.add(targetColl); if (r.size() > 0) { result.add(sr); Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/SourceFileScanner.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/SourceFileScanner.java?rev=581748&r1=581747&r2=581748&view=diff ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/util/SourceFileScanner.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/util/SourceFileScanner.java Wed Oct 3 16:44:10 2007 @@ -91,9 +91,12 @@ this.destDir = destDir; Vector v = new Vector(); for (int i = 0; i < files.length; i++) { - File src = FILE_UTILS.resolveFile(srcDir, files[i]); - v.addElement(new Resource(files[i], src.exists(), - src.lastModified(), src.isDirectory())); + final String name = files[i]; + v.addElement(new FileResource(srcDir, name) { + public String getName() { + return name; + } + }); } Resource[] sourceresources = new Resource[v.size()]; v.copyInto(sourceresources); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]