]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Improved multi-threading testbed a bit:
authorJeremias Maerki <jeremias@apache.org>
Fri, 27 Mar 2009 14:19:00 +0000 (14:19 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 27 Mar 2009 14:19:00 +0000 (14:19 +0000)
- Prints out a report with some statistics at the end.
- Worker threads moved into their own thread group for easier profiling.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@759147 13f79535-47bb-0310-9956-ffa450edef68

test/java/org/apache/fop/threading/FOPTestbed.java
test/java/org/apache/fop/threading/FOProcessor.java
test/java/org/apache/fop/threading/FOProcessorImpl.java

index 7ced868c4efb23ab03579f787646e78f8cf0e4fa..737317bec7079f39762c33818c8e2f187fa32f82 100644 (file)
@@ -20,9 +20,9 @@
 package org.apache.fop.threading;
 
 import java.io.File;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.text.DecimalFormat;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -41,6 +41,8 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.container.ContainerUtil;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CountingOutputStream;
+import org.apache.commons.io.output.NullOutputStream;
 
 /**
  * Testbed for multi-threading tests. The class can run a configurable set of task a number of
@@ -55,13 +57,17 @@ public class FOPTestbed extends AbstractLogEnabled
     private File outputDir;
     private Configuration fopCfg;
     private FOProcessor foprocessor;
+    private boolean writeToDevNull;
 
     private int counter = 0;
 
+    private List results = Collections.synchronizedList(new java.util.LinkedList());
+
     /** {@inheritDoc} */
     public void configure(Configuration configuration) throws ConfigurationException {
         this.threads = configuration.getChild("threads").getValueAsInteger(10);
         this.outputDir = new File(configuration.getChild("output-dir").getValue());
+        this.writeToDevNull = configuration.getChild("devnull").getValueAsBoolean(false);
         Configuration tasks = configuration.getChild("tasks");
         this.repeat = tasks.getAttributeAsInteger("repeat", 1);
         Configuration[] entries = tasks.getChildren("task");
@@ -85,11 +91,12 @@ public class FOPTestbed extends AbstractLogEnabled
         this.counter = 0;
 
         //Initialize threads
+        ThreadGroup workerGroup = new ThreadGroup("FOP workers");
         List threadList = new java.util.LinkedList();
         for (int ti = 0; ti < this.threads; ti++) {
             TaskRunner runner = new TaskRunner();
             ContainerUtil.enableLogging(runner, getLogger());
-            Thread thread = new Thread(runner);
+            Thread thread = new Thread(workerGroup, runner, "Worker- " + ti);
             threadList.add(thread);
         }
 
@@ -112,7 +119,38 @@ public class FOPTestbed extends AbstractLogEnabled
                 //ignore
             }
         }
-        getLogger().info("Stress test duration: " + (System.currentTimeMillis() - start) + "ms");
+        long duration = System.currentTimeMillis() - start;
+
+        report(duration);
+    }
+
+    private void report(long duration) {
+        int count = this.results.size();
+        int failures = 0;
+        long bytesWritten = 0;
+        System.out.println("Report on " + count + " tasks:");
+        Iterator iter = this.results.iterator();
+        while (iter.hasNext()) {
+            Result res = (Result)iter.next();
+            if (res.failure != null) {
+                System.out.println("FAIL: " + (res.end - res.start) + " " + res.task);
+                System.out.println("  -> " + res.failure.getMessage());
+                failures++;
+            } else {
+                System.out.println("good: " + (res.end - res.start) + " " + res.filesize
+                        + " " + res.task);
+                bytesWritten += res.filesize;
+            }
+        }
+        System.out.println("Stress test duration: " + duration + "ms");
+        if (failures > 0) {
+            System.out.println(failures + " failures of " + count + " documents!!!");
+        } else {
+            float mb = 1024f * 1024f;
+            System.out.println("Bytes written: " + (bytesWritten / mb) + " MB, "
+                    + (bytesWritten * 1000 / duration) + " bytes / sec");
+            System.out.println("NO failures with " + count + " documents.");
+        }
     }
 
     private class TaskRunner extends AbstractLogEnabled implements Runnable {
@@ -222,29 +260,61 @@ public class FOPTestbed extends AbstractLogEnabled
 
         public void execute() throws Exception {
             getLogger().info("Processing: " + def);
-            DecimalFormat df = new DecimalFormat("00000");
-            File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
-            OutputStream out = new java.io.FileOutputStream(outfile);
+            long start = System.currentTimeMillis();
             try {
-                InputStream in;
-                Templates templates;
-
-                if (def.getFO() != null) {
-                    in = new java.io.FileInputStream(new File(def.getFO()));
-                    templates = null;
+                DecimalFormat df = new DecimalFormat("00000");
+                File outfile = new File(outputDir, df.format(num) + fop.getTargetFileExtension());
+                OutputStream out;
+                if (writeToDevNull) {
+                    out = new NullOutputStream();
                 } else {
-                    in = new java.io.FileInputStream(new File(def.getXML()));
-                    templates = def.getTemplates();
+                    out = new java.io.FileOutputStream(outfile);
+                    out = new java.io.BufferedOutputStream(out);
                 }
+                CountingOutputStream cout = new CountingOutputStream(out);
                 try {
-                    fop.process(in, templates, out);
+                    Source src;
+                    Templates templates;
+
+                    if (def.getFO() != null) {
+                        src = new StreamSource(new File(def.getFO()));
+                        templates = null;
+                    } else {
+                        src = new StreamSource(new File(def.getXML()));
+                        templates = def.getTemplates();
+                    }
+                    fop.process(src, templates, cout);
                 } finally {
-                    IOUtils.closeQuietly(in);
+                    IOUtils.closeQuietly(cout);
                 }
-            } finally {
-                IOUtils.closeQuietly(out);
+                results.add(new Result(def, start, System.currentTimeMillis(),
+                        cout.getByteCount()));
+            } catch (Exception e) {
+                results.add(new Result(def, start, System.currentTimeMillis(), e));
+                throw e;
             }
         }
     }
 
+    private static class Result {
+
+        private TaskDef task;
+        private long start;
+        private long end;
+        private long filesize;
+        private Throwable failure;
+
+        public Result(TaskDef task, long start, long end, long filesize) {
+            this(task, start, end, null);
+            this.filesize = filesize;
+        }
+
+        public Result(TaskDef task, long start, long end, Throwable failure) {
+            this.task = task;
+            this.start = start;
+            this.end = end;
+            this.failure = failure;
+        }
+    }
+
 }
\ No newline at end of file
index 05c8f6fe19ea1c7f8fe6eab1a1c54fb3206dd82e..dd663da055d679c13bfde5df4f44176b2387ee20 100644 (file)
@@ -19,9 +19,9 @@
 
 package org.apache.fop.threading;
 
-import java.io.InputStream;
 import java.io.OutputStream;
 
+import javax.xml.transform.Source;
 import javax.xml.transform.Templates;
 
 /**
@@ -31,12 +31,12 @@ public interface FOProcessor {
 
     /**
      * Process a file.
-     * @param in the InputStream for the FO or XML file
+     * @param src the Source for the FO or XML file
      * @param templates a JAXP Templates object for an XSLT transformation or null
      * @param out the OutputStream for the target file
      * @throws Exception if an error occurs
      */
-    void process(InputStream in, Templates templates, OutputStream out)
+    void process(Source src, Templates templates, OutputStream out)
             throws Exception;
 
     /**
index 4ba7da658eee64169f5609a9984438828304c3ad..2b580bbd09fc6bf02a9d7848cf0bbec966e09078 100644 (file)
@@ -19,8 +19,9 @@
 
 package org.apache.fop.threading;
 
-import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
 
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
@@ -29,19 +30,23 @@ import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.stream.StreamSource;
 
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.commons.io.FilenameUtils;
 
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.Fop;
 import org.apache.fop.apps.FopFactory;
 import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.events.Event;
+import org.apache.fop.events.EventFormatter;
+import org.apache.fop.events.EventListener;
+import org.apache.fop.events.model.EventSeverity;
 
 /**
  * Default implementation of the FOProcessor interface using FOP.
@@ -71,9 +76,17 @@ public class FOProcessorImpl extends AbstractLogEnabled
     }
 
     /** {@inheritDoc} */
-    public void process(InputStream in, Templates templates, OutputStream out)
+    public void process(Source src, Templates templates, OutputStream out)
                 throws org.apache.fop.apps.FOPException, java.io.IOException {
         FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+        foUserAgent.setBaseURL(src.getSystemId());
+        try {
+            URL url = new URL(src.getSystemId());
+            String filename = FilenameUtils.getName(url.getPath());
+            foUserAgent.getEventBroadcaster().addEventListener(new AvalonAdapter(filename));
+        } catch (MalformedURLException mfue) {
+            throw new RuntimeException(mfue);
+        }
         Fop fop = fopFactory.newFop(this.mime, foUserAgent, out);
 
         try {
@@ -83,7 +96,6 @@ public class FOProcessorImpl extends AbstractLogEnabled
             } else {
                 transformer = templates.newTransformer();
             }
-            Source src = new StreamSource(in);
             Result res = new SAXResult(fop.getDefaultHandler());
             transformer.transform(src, res);
         } catch (TransformerException e) {
@@ -96,4 +108,29 @@ public class FOProcessorImpl extends AbstractLogEnabled
         return this.fileExtension;
     }
 
+    private class AvalonAdapter implements EventListener {
+
+        private String filename;
+
+        public AvalonAdapter(String filename) {
+            this.filename = filename;
+        }
+
+        public void processEvent(Event event) {
+            String msg = EventFormatter.format(event);
+            EventSeverity severity = event.getSeverity();
+            if (severity == EventSeverity.INFO) {
+                //getLogger().info(filename + ": " + msg);
+            } else if (severity == EventSeverity.WARN) {
+                //getLogger().warn(filename + ": "  + msg);
+            } else if (severity == EventSeverity.ERROR) {
+                getLogger().error(filename + ": "  + msg);
+            } else if (severity == EventSeverity.FATAL) {
+                getLogger().fatalError(filename + ": "  + msg);
+            } else {
+                assert false;
+            }
+        }
+
+    }
 }
\ No newline at end of file