Multithreaded processing on multi core or multi cpu systems.

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4870 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Xavier Le Vourch
2006-12-12 01:33:39 +00:00
parent 3bb598ccd9
commit 0f44bce4e5
17 changed files with 167 additions and 27 deletions

View File

@ -13,5 +13,6 @@
<classpathentry kind="var" path="JDK1.5_HOME/lib/tools.jar"/>
<classpathentry kind="lib" path="lib/jaxen-1.1-beta-10.jar"/>
<classpathentry kind="lib" path="lib/asm-3.0.jar"/>
<classpathentry kind="lib" path="lib/backport-util-concurrent.jar"/>
<classpathentry kind="output" path="build"/>
</classpath>

View File

@ -1 +1 @@
java -cp ../build;../lib/asm-3.0.jar;../lib/pmd-3.8.jar;../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.viewer.Viewer
java -cp ../build;../lib/asm-3.0.jar;../lib/backport-util-concurrent.jar;../lib/pmd-3.8.jar;../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.viewer.Viewer

View File

@ -1 +1 @@
java -cp ../build:../lib/asm-3.0.jar:../lib/pmd-3.8.jar:../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.viewer.Viewer
java -cp ../build:../lib/asm-3.0.jar:../lib/backport-util-concurrent.jar:../lib/pmd-3.8.jar:../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.viewer.Viewer

View File

@ -18,6 +18,7 @@
<fileset dir="${dir.lib}">
<include name="jaxen-1.1-beta-10.jar" />
<include name="asm-3.0.jar" />
<include name="backport-util-concurrent.jar" />
</fileset>
</path>
@ -66,7 +67,7 @@
<jar jarfile="${dir.lib}\pmd-${version}.jar" includes="net/sourceforge/pmd/**/**,test/net/sourceforge/pmd/testframework/**/**,rulesets/**" basedir="${dir.build}">
<manifest>
<attribute name="Main-Class" value="net.sourceforge.pmd.PMD" />
<attribute name="Class-Path" value="jaxen-1.1-beta-10.jar asm-3.0.jar" />
<attribute name="Class-Path" value="jaxen-1.1-beta-10.jar asm-3.0.jar backport-util-concurrent.jar" />
</manifest>
</jar>
</target>

View File

@ -6,7 +6,7 @@ esac
FILE=$1
FORMAT=$2
RULESETFILES=$3
PMD_CLASSPATH=../lib/pmd-3.8.jar:../lib/jaxen-1.1-beta-10.jar:../lib/asm-3.0.jar
PMD_CLASSPATH=../lib/pmd-3.8.jar:../lib/jaxen-1.1-beta-10.jar:../lib/backport-util-concurrent.jar:../lib/asm-3.0.jar
if $cygwin; then
FILE=`cygpath --windows "$FILE"`
PMD_CLASSPATH=`cygpath --path --windows "$PMD_CLASSPATH"`

View File

@ -1 +1 @@
java -cp ../build;../lib/asm-3.0.jar;../lib/pmd-3.8.jar;../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.designer.Designer
java -cp ../build;../lib/asm-3.0.jar;../lib/backport-util-concurrent.jar;../lib/pmd-3.8.jar;../lib/jaxen-1.1-beta-10.jar net.sourceforge.pmd.util.designer.Designer

View File

@ -1,2 +1,2 @@
@echo off
java -cp %~dp0\..\lib\pmd-3.8.jar;%~dp0\..\lib\jaxen-1.1-beta-10.jar;%~dp0\..\lib\asm-3.0.jar;%CLASSPATH% net.sourceforge.pmd.PMD %*
java -cp %~dp0\..\lib\pmd-3.8.jar;%~dp0\..\lib\jaxen-1.1-beta-10.jar;%~dp0\..\lib\asm-3.0.jar;%~dp0\..\lib\backport-util-concurrent.jar;%~dp0\..\lib\backport-util-concurrent.jar;%CLASSPATH% net.sourceforge.pmd.PMD %*

View File

@ -7,6 +7,7 @@ set PATH=c:\j2sdk1.4.2_04\bin;c:\ant\bin\;%PATH%
set CLASSPATH=../build/
set CLASSPATH=%CLASSPATH%;../
set CLASSPATH=%CLASSPATH%;../lib/asm-3.0.jar
set CLASSPATH=%CLASSPATH%;../lib/backport-util-concurrent.jar
set CLASSPATH=%CLASSPATH%;../lib/jaxen-1.1-beta-10.jar
set CLASSPATH=%CLASSPATH%;c:\javacc2.1\bin\lib\JavaCC.zip
set CLASSPATH=%CLASSPATH%;c:\ant\lib\ant.jar

View File

@ -4,5 +4,5 @@ PATH=/usr/local/java/bin/:$PATH
ANT_OPTS=-Xmx512m
PATH=$MAVEN_HOME/bin:$PATH
CVSROOT=:ext:tomcopeland@cvs.sourceforge.net:/cvsroot/pmd
CLASSPATH=../build/:../lib/asm-3.0.jar:../lib/jaxen-1.1-beta-10.jar:/usr/local/junit/junit.jar:/usr/local/ant/lib/ant.jar:/usr/local/ant/lib/ant-nodeps.jar
CLASSPATH=../build/:../lib/asm-3.0.jar:../lib/backport-util-concurrent.jar:../lib/jaxen-1.1-beta-10.jar:/usr/local/junit/junit.jar:/usr/local/ant/lib/ant.jar:/usr/local/ant/lib/ant-nodeps.jar
export CLASSPATH PATH CVSROOT ANT_OPTS

View File

@ -50,6 +50,7 @@ use of entrySet to iterate over Maps.
PMD now allows rules to use Type Resolution. This was referenced in patch 1257259.
Renderers use less memory when generating reports.
New DynamicXPathRule class to speed up XPath based rules by providing a base type for the XPath expression.
Multithreaded processing on multi core or multi cpu systems.
Performance Refactoring, XPath rules re-written as Java:
AssignmentInOperand
AvoidDollarSigns

View File

@ -33,7 +33,7 @@ cp ../LICENSE.txt changelog.txt ~/tmp/pmd-3.8/etc
cd ../bin/
cp pmd.* cygwin-run.sh build.xml cpd.sh cpdgui.bat designer.* ~/tmp/pmd-3.8/bin
cd ../etc/
cp ../lib/pmd-3.8.jar ../lib/asm-3.0.jar ../lib/jaxen-1.1-beta-10.jar ~/tmp/pmd-3.8/lib/
cp ../lib/pmd-3.8.jar ../lib/asm-3.0.jar ../lib/backport-util-concurrent.jar ../lib/jaxen-1.1-beta-10.jar ~/tmp/pmd-3.8/lib/
mkdir ~/tmp/pmd-3.8/etc/xslt
cp xslt/*.xslt xslt/*.js xslt/*.gif xslt/*.css ~/tmp/pmd-3.8/etc/xslt/
cp -R ../target/docs ~/tmp/pmd-3.8

Binary file not shown.

View File

@ -233,6 +233,10 @@
<id>asm</id>
<version>3.0</version>
</dependency>
<dependency>
<id>backport-util-concurrent</id>
<version>3.0</version>
</dependency>
</dependencies>
<build>

View File

@ -13,7 +13,6 @@ import net.sourceforge.pmd.sourcetypehandlers.SourceTypeHandlerBroker;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -25,6 +24,11 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
import edu.emory.mathcs.backport.java.util.concurrent.Executors;
import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@ -228,25 +232,24 @@ public class PMD {
files = collectFilesFromOneName(opts.getInputPath(), fileSelector);
}
PMD pmd = new PMD();
SourceType sourceType;
if (opts.getTargetJDK().equals("1.3")) {
if (opts.debugEnabled())
System.out.println("In JDK 1.3 mode");
pmd.setJavaVersion(SourceType.JAVA_13);
sourceType = SourceType.JAVA_13;
} else if (opts.getTargetJDK().equals("1.5")) {
if (opts.debugEnabled())
System.out.println("In JDK 1.5 mode");
pmd.setJavaVersion(SourceType.JAVA_15);
sourceType = SourceType.JAVA_15;
} else if (opts.getTargetJDK().equals("1.6")) {
if (opts.debugEnabled())
System.out.println("In JDK 1.6 mode");
pmd.setJavaVersion(SourceType.JAVA_16);
sourceType = SourceType.JAVA_16;
} else {
if (opts.debugEnabled())
System.out.println("In JDK 1.4 mode");
pmd.setJavaVersion(SourceType.JAVA_14);
sourceType = SourceType.JAVA_14;
}
pmd.setExcludeMarker(opts.getExcludeMarker());
RuleContext ctx = new RuleContext();
Report report = new Report();
@ -256,14 +259,14 @@ public class PMD {
try {
RuleSetFactory ruleSetFactory = new RuleSetFactory();
ruleSetFactory.setMinimumPriority(opts.getMinPriority());
RuleSets rulesets = ruleSetFactory.createRuleSets(opts.getRulesets());
printRuleNamesInDebug(opts.debugEnabled(), rulesets);
pmd.processFiles(files, ctx, rulesets, opts.debugEnabled(), opts
.shortNamesEnabled(), opts.getInputPath(), opts.getEncoding());
} catch (FileNotFoundException fnfe) {
System.out.println(opts.usage());
fnfe.printStackTrace();
int threadCount = Runtime.getRuntime().availableProcessors();
processFiles(threadCount, ruleSetFactory, sourceType, files, ctx,
opts.getRulesets(), opts.debugEnabled(), opts.shortNamesEnabled(),
opts.getInputPath(), opts.getEncoding(), opts.getExcludeMarker());
} catch (RuleSetNotFoundException rsnfe) {
System.out.println(opts.usage());
rsnfe.printStackTrace();
@ -288,6 +291,135 @@ public class PMD {
}
}
private static class PmdRunnable extends PMD implements Runnable {
private final InputStream inputStream;
private final String fileName;
private final boolean debugEnabled;
private final String encoding;
private final String rulesets;
public PmdRunnable(InputStream inputStream, String fileName, SourceType sourceType,
boolean debugEnabled, String encoding, String rulesets, String excludeMarker) {
this.inputStream = inputStream;
this.fileName = fileName;
this.debugEnabled = debugEnabled;
this.encoding = encoding;
this.rulesets = rulesets;
setJavaVersion(sourceType);
setExcludeMarker(excludeMarker);
}
public void run() {
PmdThread thread = (PmdThread) Thread.currentThread();
RuleContext ctx = thread.getRuleContext();
RuleSets rs = thread.getRuleSets(rulesets);
ctx.setSourceCodeFilename(fileName);
if (debugEnabled) {
System.out.println("Processing " + ctx.getSourceCodeFilename());
}
try {
InputStream stream = new BufferedInputStream(inputStream);
processFile(stream, encoding, rs, ctx);
} catch (PMDException pmde) {
if (debugEnabled) {
pmde.getReason().printStackTrace();
}
ctx.getReport().addError(
new Report.ProcessingError(pmde.getMessage(),
fileName));
}
}
}
private static class PmdThreadFactory implements ThreadFactory {
public PmdThreadFactory(Report report, RuleSetFactory ruleSetFactory) {
this.report = report;
this.ruleSetFactory = ruleSetFactory;
}
private final Report report;
private final RuleSetFactory ruleSetFactory;
private final AtomicInteger counter = new AtomicInteger();
public Thread newThread(Runnable r) {
return new PmdThread(counter.incrementAndGet(), r, report, ruleSetFactory);
}
}
private static class PmdThread extends Thread {
public PmdThread(int id, Runnable r, Report report, RuleSetFactory ruleSetFactory) {
super(r, "PmdThread " + id);
this.id = id;
context = new RuleContext();
context.setReport(report);
this.ruleSetFactory = ruleSetFactory;
}
private int id;
private RuleContext context;
private RuleSets rulesets;
private RuleSetFactory ruleSetFactory;
public RuleContext getRuleContext() {
return context;
}
public RuleSets getRuleSets(String rsList) {
if (rulesets == null) {
try {
rulesets = ruleSetFactory.createRuleSets(rsList);
} catch (Exception e) {
e.printStackTrace();
}
}
return rulesets;
}
public String toString() {
return "PmdThread " + id;
}
}
/**
* Run PMD on a list of files using multiple threads.
*
* @throws IOException If one of the files could not be read
*/
public static void processFiles(int threadCount, RuleSetFactory ruleSetFactory, SourceType sourceType, List files, RuleContext ctx, String rulesets,
boolean debugEnabled, boolean shortNamesEnabled, String inputPath,
String encoding, String excludeMarker) throws IOException {
PmdThreadFactory factory = new PmdThreadFactory(ctx.getReport(), ruleSetFactory);
ExecutorService executor = Executors.newFixedThreadPool(threadCount, factory);
for (Iterator i = files.iterator(); i.hasNext();) {
DataSource dataSource = (DataSource) i.next();
String niceFileName = dataSource.getNiceFileName(shortNamesEnabled,
inputPath);
InputStream is = dataSource.getInputStream();
Runnable r = new PmdRunnable(is, niceFileName, sourceType, debugEnabled,
encoding, rulesets, excludeMarker);
executor.execute(r);
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
}
/**
* Run PMD on a list of files.
*

View File

@ -175,7 +175,7 @@ public class Report {
return suppressedRuleViolations;
}
public void addRuleViolation(IRuleViolation violation) {
public synchronized void addRuleViolation(IRuleViolation violation) {
// NOPMD excluder
Integer line = new Integer(violation.getBeginLine());
@ -198,7 +198,7 @@ public class Report {
}
}
public void addMetric(Metric metric) {
public synchronized void addMetric(Metric metric) {
metrics.add(metric);
for (Iterator i = listeners.iterator(); i.hasNext();) {
ReportListener listener = (ReportListener) i.next();
@ -206,7 +206,7 @@ public class Report {
}
}
public void addError(ProcessingError error) {
public synchronized void addError(ProcessingError error) {
errors.add(error);
}

View File

@ -214,7 +214,7 @@ try deleting the ruleset.xml file in the .metadata/plugins/net.sourceforge.pmd.e
<li>Menu: Select the "Main menu", "Project views", "Editor menu", and "Search results" checkboxes.</li>
<li>Program: $JDKPath$\bin\java.exe</li>
<li>For the next parameter you'll need to plug in the location of your PMD installation and the rulesets you want to use</li>
<li>Parameters: -cp %CLASSPATH%;c:\pmd\lib\pmd-3.8.jar;c:\pmd\lib\asm-3.0.jar;c:\pmd\lib\jaxen-1.1-beta-10.jar net.sourceforge.pmd.PMD "$FilePath$" ideaj unusedcode,imports "$Sourcepath$" $FileClass$.method $FileName$ </li>
<li>Parameters: -cp %CLASSPATH%;c:\pmd\lib\pmd-3.8.jar;c:\pmd\lib\asm-3.0.jar;c:\pmd\lib\backport-util-concurrent.jar;c:\pmd\lib\jaxen-1.1-beta-10.jar net.sourceforge.pmd.PMD "$FilePath$" ideaj unusedcode,imports "$Sourcepath$" $FileClass$.method $FileName$ </li>
</ul>
</ul>
<p>That's pretty much it. Now you can right click on a source directory and select PMD, it'll run recursively on the source files, and the results should
@ -348,8 +348,8 @@ selecting the "Ask for Directory" checkbox.</p>
<LI>Expand the <B>Tools</B> branch (if not already) by clicking on the '<CODE>+</CODE>' directly to its left.</LI>
<LI>In the expanded list, select <B>PMD directory</B>. This changes the right side of this dialog to the "tool" form.</LI>
<LI>In the "tool" form, enter these parameters:<UL>
<LI><B>Parameters:</B> <CODE>-classpath D:\java\pmd-3.8\lib\pmd-3.8.jar;D:\java\pmd-3.8\lib\asm-3.0.jar;D:\java\pmd-3.8\lib\jaxen-1.1-beta-10.jar net.sourceforge.pmd.PMD <I><B>$FileDir</B></I> net.sourceforge.pmd.renderers.TextPadRenderer E:\directory\my_pmd_ruleset.xml -debug</CODE>
<BR/>(<I>Eliminate the spaces following both '<CODE>jaxen-1.1-beta-10.jar;</CODE>' and '<CODE>asm-3.0.jar;</CODE>'. They are there to prevent the text from exceeding the right side of your screen</I>)</LI>
<LI><B>Parameters:</B> <CODE>-classpath D:\java\pmd-3.8\lib\pmd-3.8.jar;D:\java\pmd-3.8\lib\asm-3.0.jar;D:\java\pmd-3.8\lib\backport-util-concurrent.jar;D:\java\pmd-3.8\lib\jaxen-1.1-beta-10.jar net.sourceforge.pmd.PMD <I><B>$FileDir</B></I> net.sourceforge.pmd.renderers.TextPadRenderer E:\directory\my_pmd_ruleset.xml -debug</CODE>
<BR/>(<I>Eliminate the spaces following '<CODE>jaxen-1.1-beta-10.jar;</CODE>', '<CODE>asm-3.0.jar;</CODE>' and '<CODE>backport-util-concurrent.jar;</CODE>'. They are there to prevent the text from exceeding the right side of your screen</I>)</LI>
<LI><B>Initial Folder:</B> <CODE>$FileDir</CODE></LI>
<LI><B>Save all documents first:</B> <CODE>Checked</CODE></LI>
<LI><B>Capture output:</B> <CODE>Checked</CODE></LI>

View File

@ -31,7 +31,7 @@ C:\tmp\pmd-3.8\pmd\bin&gt;
<li>If you are want to run PMD without the batch file, you can do a:</li>
<source>
C:\data\pmd\pmd>java -cp lib\pmd-3.8.jar;lib\jaxen-1.1-beta-10.jar;lib\asm-3.0.jar
C:\data\pmd\pmd>java -cp lib\pmd-3.8.jar;lib\jaxen-1.1-beta-10.jar;lib\asm-3.0.jar;lib\backport-util-concurrent.jar
net.sourceforge.pmd.PMD
c:\j2sdk1.4.1_01\src\java\lang xml
rulesets/imports.xml