View Javadoc

1   /**
2    * Copyright (c) 2012, University of Konstanz, Distributed Systems Group
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    * * Redistributions of source code must retain the above copyright
8    * notice, this list of conditions and the following disclaimer.
9    * * Redistributions in binary form must reproduce the above copyright
10   * notice, this list of conditions and the following disclaimer in the
11   * documentation and/or other materials provided with the distribution.
12   * * Neither the name of the University of Konstanz nor the
13   * names of its contributors may be used to endorse or promote products
14   * derived from this software without specific prior written permission.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package org.perfidix.ouput;
28  
29  import java.io.PrintStream;
30  import java.lang.reflect.Method;
31  
32  import org.perfidix.exceptions.AbstractPerfidixMethodException;
33  import org.perfidix.exceptions.PerfidixMethodInvocationException;
34  import org.perfidix.meter.AbstractMeter;
35  import org.perfidix.ouput.asciitable.NiceTable;
36  import org.perfidix.ouput.asciitable.AbstractTabularComponent.Alignment;
37  import org.perfidix.result.AbstractResult;
38  import org.perfidix.result.BenchmarkResult;
39  import org.perfidix.result.ClassResult;
40  import org.perfidix.result.MethodResult;
41  
42  /**
43   * Summary output using the {@link NiceTable} to format. Just giving an overview
44   * of statistical analysis over the results.
45   * 
46   * @author Sebastian Graf, University of Konstanz
47   */
48  public final class TabularSummaryOutput extends AbstractOutput {
49  
50      /** Print stream where the result should end. */
51      private transient final PrintStream out;
52  
53      /**
54       * Constructor for piping the result to elsewhere.
55       * 
56       * @param paramOut
57       *            an {@link PrintStream} to pipe to.
58       */
59      public TabularSummaryOutput(final PrintStream paramOut) {
60          super();
61          out = paramOut;
62      }
63  
64      /**
65       * Constructor, just giving out on the {@link System#out}.
66       */
67      public TabularSummaryOutput() {
68          this(System.out);
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public void visitBenchmark(final BenchmarkResult benchRes) {
74          final int numberOfColumns = 9;
75          NiceTable table = new NiceTable(numberOfColumns);
76          table = generateHeader(table);
77          for (final AbstractMeter meter : benchRes.getRegisteredMeters()) {
78              table.addHeader(meter.getName(), '=', Alignment.Center);
79              for (final ClassResult classRes : benchRes.getIncludedResults()) {
80                  table.addHeader(classRes.getElementName(), '.', Alignment.Left);
81                  for (final MethodResult methRes : classRes.getIncludedResults()) {
82                      table = generateMeterResult(methRes.getElementName(), meter, methRes, table);
83                  }
84  
85                  table.addHeader(new StringBuilder("Summary for ").append(classRes.getElementName())
86                      .toString(), '_', Alignment.Left);
87                  table = generateMeterResult("", meter, classRes, table);
88                  table.addLine('-');
89  
90              }
91          }
92          table.addHeader("Summary for the whole benchmark", '=', Alignment.Center);
93  
94          for (final AbstractMeter meter : benchRes.getRegisteredMeters()) {
95              table = generateMeterResult("", meter, benchRes, table);
96          }
97  
98          table.addHeader("Exceptions", '=', Alignment.Center);
99          for (final AbstractPerfidixMethodException exec : benchRes.getExceptions()) {
100             final StringBuilder execBuilder0 = new StringBuilder();
101             execBuilder0.append("Related exception: ").append(exec.getExec().getClass().getSimpleName());
102             table.addHeader(execBuilder0.toString(), ' ', Alignment.Left);
103 
104             final StringBuilder execBuilder1 = new StringBuilder();
105             if (exec instanceof PerfidixMethodInvocationException) {
106                 execBuilder1.append("Related place: method invocation");
107             } else {
108                 execBuilder1.append("Related place: method check");
109             }
110             table.addHeader(execBuilder1.toString(), ' ', Alignment.Left);
111             if (exec.getMethod() != null) {
112                 final StringBuilder execBuilder2 = new StringBuilder();
113                 execBuilder2.append("Related method: ").append(exec.getMethod().getName());
114                 table.addHeader(execBuilder2.toString(), ' ', Alignment.Left);
115             }
116             final StringBuilder execBuilder3 = new StringBuilder();
117             execBuilder3.append("Related annotation: ").append(exec.getRelatedAnno().getSimpleName());
118             table.addHeader(execBuilder3.toString(), ' ', Alignment.Left);
119             table.addLine('-');
120 
121         }
122         table.addLine('=');
123         out.println(table.toString());
124     }
125 
126     /**
127      * Generating the results for a given table.
128      * 
129      * @param columnDesc
130      *            the description for the row
131      * @param meter
132      *            the corresponding {@link AbstractMeter} instance
133      * @param result
134      *            the corresponding {@link AbstractResult} instance
135      * @param input
136      *            the {@link NiceTable} to be print to
137      * @return the modified {@link NiceTable} instance
138      */
139     private NiceTable generateMeterResult(final String columnDesc, final AbstractMeter meter,
140         final AbstractResult result, final NiceTable input) {
141         input.addRow(new String[] {
142             columnDesc,
143             meter.getUnit(),
144             AbstractOutput.format(result.sum(meter)),
145             AbstractOutput.format(result.min(meter)),
146             AbstractOutput.format(result.max(meter)),
147             AbstractOutput.format(result.mean(meter)),
148             AbstractOutput.format(result.getStandardDeviation(meter)),
149             new StringBuilder("[").append(AbstractOutput.format(result.getConf05(meter))).append("-").append(
150                 AbstractOutput.format(result.getConf95(meter))).append("]").toString(),
151             AbstractOutput.format(result.getResultSet(meter).size())
152         });
153         return input;
154     }
155 
156     /**
157      * {@inheritDoc}
158      */
159     @Override
160     public boolean listenToResultSet(final Method meth, final AbstractMeter meter, final double data) {
161         final StringBuilder builder = new StringBuilder();
162         builder.append("Class: ").append(meth.getDeclaringClass().getSimpleName()).append("#").append(
163             meth.getName());
164         builder.append("\nMeter: ").append(meter.getName());
165         builder.append("\nData: ").append(data).append("\n");
166         out.println(builder.toString());
167         return true;
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public boolean listenToException(final AbstractPerfidixMethodException exec) {
173         final StringBuilder builder = new StringBuilder();
174         if (exec.getMethod() != null) {
175             builder.append("Class: ").append(exec.getMethod().getDeclaringClass().getSimpleName())
176                 .append("#").append(exec.getMethod().getName()).append("\n");
177         }
178         builder.append("Annotation: ").append(exec.getRelatedAnno().getSimpleName());
179         builder.append("\nException: ").append(exec.getClass().getSimpleName()).append("/").append(
180             exec.getExec().toString());
181         out.println(builder.toString());
182         exec.getExec().printStackTrace(out);
183         return true;
184 
185     }
186 
187     /**
188      * Generating header for a given table.
189      * 
190      * @param table
191      *            the table where the header should fit to
192      * @return another {@link NiceTable} instance
193      */
194     private NiceTable generateHeader(final NiceTable table) {
195         table.addHeader("Benchmark");
196         table.addRow(new String[] {
197             "-", "unit", "sum", "min", "max", "avg", "stddev", "conf95", "runs"
198         });
199         return table;
200     }
201 
202 }