From: <ls...@us...> - 2011-07-15 19:32:59
|
Revision: 5833 http://jnode.svn.sourceforge.net/jnode/?rev=5833&view=rev Author: lsantha Date: 2011-07-15 19:32:53 +0000 (Fri, 15 Jul 2011) Log Message: ----------- Performance optimization for CompareTask. Modified Paths: -------------- classlib6/builder/src/builder/org/jnode/ant/taskdefs/classpath/CompareTask.java Modified: classlib6/builder/src/builder/org/jnode/ant/taskdefs/classpath/CompareTask.java =================================================================== --- classlib6/builder/src/builder/org/jnode/ant/taskdefs/classpath/CompareTask.java 2011-07-15 18:38:45 UTC (rev 5832) +++ classlib6/builder/src/builder/org/jnode/ant/taskdefs/classpath/CompareTask.java 2011-07-15 19:32:53 UTC (rev 5833) @@ -28,10 +28,21 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Execute; @@ -42,6 +53,7 @@ * version of classpath. * * @author Ewout Prangsma (ep...@us...) + * @author Levente S\u00e1ntha */ public class CompareTask extends Task { @@ -90,6 +102,94 @@ private static final int FLAG_UNSUBMITTED_CLASSPATH_BUGFIX = 0x2000; + private abstract class CompareResult implements Comparable { + final String fileName; + final String reportName; + + protected CompareResult(String fileName, String reportName) { + this.fileName = fileName; + this.reportName = reportName; + } + + abstract void reportResult(PrintWriter pw); + + @Override + public int compareTo(Object o) { + return this.fileName.compareTo(((CompareResult)o).fileName); + } + } + + private class VmSpecificResult extends CompareResult { + private VmSpecificResult(String fileName, String reportName) { + super(fileName, reportName); + } + + @Override + void reportResult(PrintWriter out) { + reportVmSpecific(out, reportName, "vm-specific"); + } + } + + private class MissingResult extends CompareResult { + final String type; + final Flags flags; + private MissingResult(String fileName, String reportName, String type, Flags flags) { + super(fileName, reportName); + this.type = type; + this.flags = flags; + } + + @Override + void reportResult(PrintWriter out) { + reportMissing(out, reportName, type, flags); + } + } + + private class NeedsMergeResult extends CompareResult { + final Flags flags; + final String target; + final String diffFile; + private NeedsMergeResult(String fileName, String reportName, String target, String diffFile, Flags flags) { + super(fileName, reportName); + this.target = target; + this.diffFile = diffFile; + this.flags = flags; + } + + @Override + void reportResult(PrintWriter out) { + reportNeedsMerge(out, reportName, target, diffFile, flags.mask(FLAGS_MASK)); + } + } + + private class ClasspathBugsResult extends CompareResult { + final Flags flags; + final String target; + private ClasspathBugsResult(String fileName, String reportName, String target, Flags flags) { + super(fileName, reportName); + this.target = target; + this.flags = flags; + } + + @Override + void reportResult(PrintWriter out) { + reportClasspathBugs(out, reportName, target, flags); + } + } + + private class CounterResult extends CompareResult { + final String counter; + private CounterResult(String fileName, String counter) { + super(fileName, ""); + this.counter = counter; + } + + @Override + void reportResult(PrintWriter out) { + //do nothing + } + } + public void execute() { if (destDir == null) throw new BuildException("The destdir attribute must be set"); @@ -97,13 +197,11 @@ if (type == null) throw new BuildException("The type attribute must be set"); + log("Comparing files"); - final Map<String, SourceFile> vmFiles = vmDirs - .scanJavaFiles(getProject()); - final Map<String, SourceFile> classpathFiles = classpathDirs - .scanJavaFiles(getProject()); - final Map<String, SourceFile> vmSpecificFiles = vmSpecificDirs - .scanJavaFiles(getProject()); + final Map<String, SourceFile> vmFiles = vmDirs.scanJavaFiles(getProject()); + final Map<String, SourceFile> classpathFiles = classpathDirs.scanJavaFiles(getProject()); + final Map<String, SourceFile> vmSpecificFiles = vmSpecificDirs.scanJavaFiles(getProject()); final TreeSet<String> allFiles = new TreeSet<String>(); final Map<String, String> packageDiffs = new TreeMap<String, String>(); allFiles.addAll(vmFiles.keySet()); @@ -111,6 +209,108 @@ try { destDir.mkdirs(); + + int n = Runtime.getRuntime().availableProcessors() * 2; + + ExecutorService es = Executors.newFixedThreadPool(n); + + class CompareCallable implements Callable<Collection<CompareResult>> { + private Collection<String> files; + + CompareCallable(Collection<String> files) { + this.files = files; + } + + @Override + public Collection<CompareResult> call() throws Exception { + ArrayList<CompareResult> results = new ArrayList<CompareResult>(); + for (String name : files) { + SourceFile cpFile = classpathFiles.get(name); + final SourceFile vmFile = vmFiles.get(name); + final SourceFile vmSpecificFile = vmSpecificFiles.get(name); + + if (vmSpecificFile != null) { + // File is found as vm specific source + results.add(new VmSpecificResult(name, vmSpecificFile.getReportName())); + } else if (vmFile == null) { + // file is not found as vmspecific source, nor as vm source + if (!cpFile.isIgnoreMissing()) { + results.add(new MissingResult(name, cpFile.getReportName(), type, getFlags(cpFile))); + } + } else if (cpFile == null) { + // File is not found in classpath sources + results.add(new MissingResult(name, vmFile.getReportName(), "vm", new Flags())); + } else { + // We have both the classpath version and the vm version. + cpFile = cpFile.getBestFileForTarget(vmFile.getTarget()); + // Let's compare them + final String diffFileName = vmFile.getReportName() + ".diff"; + Flags rc = runDiff(vmFile, cpFile, diffFileName, packageDiffs); + switch (rc.asInt() & ~FLAGS_MASK) { + case NO_CHANGE: + break; + case NEEDS_MERGE: + results.add(new NeedsMergeResult(name, vmFile.getReportName(), vmFile.getTarget(), diffFileName, rc.mask(FLAGS_MASK))); + break; + default: + throw new RuntimeException("Invalid rc " + rc); + } + if (rc.isSet(FLAG_VM_SPECIFIC)) { + results.add(new CounterResult(name, "FLAG_VM_SPECIFIC")); + } + if (rc.isSet(FLAG_CLASSPATH_BUGFIX)) { + results.add(new CounterResult(name, "FLAG_CLASSPATH_BUGFIX")); + } + if (rc.isSet(FLAG_NATIVE)) { + results.add(new CounterResult(name, "FLAG_NATIVE")); + } + if (rc.isSet(FLAG_JNODE)) { + results.add(new CounterResult(name, "FLAG_JNODE")); + } + + if (rc.getBugIDs().length > 0) { + results.add(new ClasspathBugsResult(name, vmFile.getReportName(), vmFile.getTarget(), rc)); + } + } + } + return results; + } + } + + + ArrayList<String> al = new ArrayList<String>(); + al.addAll(allFiles); + + CompareCallable[] tasks = new CompareCallable[n]; + + for(int i = 0; i < n; i++) { + tasks[i] = new CompareCallable(al.subList(i * al.size() / n, (i + 1) * al.size() / n)); + } + + List<Future<Collection<CompareResult>>> futures = es.invokeAll(Arrays.asList(tasks)); + + es.shutdown(); + es.awaitTermination(1, TimeUnit.HOURS); + + ArrayList<CompareResult> results = new ArrayList<CompareResult>(); + + for(Future<Collection<CompareResult>> future : futures){ + if(future.isDone()) { + try { + results.addAll(future.get()); + } catch (ExecutionException x) { + throw new RuntimeException(x); + } + } else { + throw new RuntimeException("Future is not done: " + future); + } + + } + + Collections.sort(results); + + log("Generating reports"); + final File outBugsFile = new File(destDir, "bugfix.html"); final PrintWriter outBugs = new PrintWriter(new FileWriter(outBugsFile)); reportHeader(outBugs, "Class", "Target", "Classpath bugs"); @@ -128,61 +328,36 @@ int diffJNode = 0; int vmSpecific = 0; - for (String name : allFiles) { - SourceFile cpFile = classpathFiles.get(name); - final SourceFile vmFile = vmFiles.get(name); - final SourceFile vmSpecificFile = vmSpecificFiles - .get(name); - - if (vmSpecificFile != null) { - // File is found as vm specific source - reportVmSpecific(out, vmSpecificFile.getReportName(), - "vm-specific"); + for (CompareResult result : results) { + if (result instanceof VmSpecificResult) { + result.reportResult(out); vmSpecific++; - } else if (vmFile == null) { - // file is not found as vmspecific source, nor as vm source - if (!cpFile.isIgnoreMissing()) { - reportMissing(out, cpFile.getReportName(), type, - getFlags(cpFile)); + } else if (result instanceof MissingResult) { + result.reportResult(out); + MissingResult missingResult = (MissingResult) result; + if(missingResult.type.equals("vm")) { + missingInCp++; + } else { missingInVm++; } - } else if (cpFile == null) { - // File is not found in classpath sources - reportMissing(out, vmFile.getReportName(), "vm", new Flags()); - missingInCp++; - } else { - // We have both the classpath version and the vm version. - cpFile = cpFile.getBestFileForTarget(vmFile.getTarget()); - - // Let's compare them - final String diffFileName = vmFile.getReportName() + ".diff"; - Flags rc = runDiff(vmFile, cpFile, diffFileName, packageDiffs); - switch (rc.asInt() & ~FLAGS_MASK) { - case NO_CHANGE: - break; - case NEEDS_MERGE: - reportNeedsMerge(out, vmFile.getReportName(), vmFile - .getTarget(), diffFileName, rc.mask(FLAGS_MASK)); - needsMerge++; - break; - default: - throw new RuntimeException("Invalid rc " + rc); - } - if (rc.isSet(FLAG_VM_SPECIFIC)) { + } else if (result instanceof NeedsMergeResult) { + result.reportResult(out); + needsMerge++; + } else if (result instanceof CounterResult) { + CounterResult counterResult = (CounterResult) result; + if (counterResult.counter.equals("FLAG_VM_SPECIFIC")) { diffVmSpecific++; - } - if (rc.isSet(FLAG_CLASSPATH_BUGFIX)) { + } else if (counterResult.counter.equals("FLAG_CLASSPATH_BUGFIX")) { diffClasspathBugfix++; - } - if (rc.isSet(FLAG_NATIVE)) { + } else if (counterResult.counter.equals("FLAG_NATIVE")) { diffNative++; - } - if (rc.isSet(FLAG_JNODE)) { + } else if (counterResult.counter.equals("FLAG_JNODE")) { diffJNode++; } - - reportClasspathBugs(outBugs, vmFile.getReportName(), vmFile - .getTarget(), rc); + } else if(result instanceof ClasspathBugsResult) { + result.reportResult(outBugs); + } else { + new RuntimeException("Unknown compare result: " + result); } } @@ -200,23 +375,19 @@ // Summary out.println("<a name='summary'/><h2>Summary</h2>"); if (missingInCp > 0) { - out.println("Found " + missingInCp - + " files missing in " + type + "</br>"); + out.println("Found " + missingInCp + " files missing in " + type + "</br>"); log("Found " + missingInCp + " files missing in " + type); } if (missingInVm > 0) { - out.println("Found " + missingInVm - + " files missing in vm<br/>"); + out.println("Found " + missingInVm + " files missing in vm<br/>"); log("Found " + missingInVm + " files missing in vm"); } if (needsMerge > 0) { - out.println("Found " + needsMerge - + " files that needs merging<br/>"); + out.println("Found " + needsMerge + " files that needs merging<br/>"); log("Found " + needsMerge + " files that needs merging"); } if (diffVmSpecific > 0) { - out.println("Found " + diffVmSpecific - + " VM specific differences<br/>"); + out.println("Found " + diffVmSpecific + " VM specific differences<br/>"); log("Found " + diffVmSpecific + " VM specific differences"); } if (vmSpecific > 0) { @@ -224,19 +395,16 @@ log("Found " + vmSpecific + " VM specific files"); } if (diffClasspathBugfix > 0) { - out.println("Found " + diffClasspathBugfix - + " local <a href=\"bugfix.html\">classpath bugfixes</a><br/>"); - log("Found " + diffClasspathBugfix - + " local classpath bugfixes"); + out.println("Found " + diffClasspathBugfix + + " local <a href=\"bugfix.html\">classpath bugfixes</a><br/>"); + log("Found " + diffClasspathBugfix + " local classpath bugfixes"); } if (diffNative > 0) { - out.println("Found " + diffNative - + " changes with native in it<br/>"); + out.println("Found " + diffNative + " changes with native in it<br/>"); log("Found " + diffNative + " changes with native in it"); } if (diffJNode > 0) { - out.println("Found " + diffJNode - + " changes with JNode in it<br/>"); + out.println("Found " + diffJNode + " changes with JNode in it<br/>"); log("Found " + diffJNode + " changes with JNode in it"); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |