001: /*
002: * Primitive Collections for Java.
003: * Copyright (C) 2003 Søren Bak
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package bak.pcj.benchmark;
020:
021: import java.util.List;
022: import java.util.ArrayList;
023: import java.util.TreeMap;
024: import java.util.Map;
025: import java.util.Collection;
026: import java.util.Iterator;
027: import java.util.Collections;
028: import java.util.Set;
029: import java.util.HashSet;
030: import java.util.TreeSet;
031:
032: import java.io.Writer;
033: import java.io.Reader;
034: import java.io.IOException;
035:
036: /**
037: * This class represents reports of results from benchmarks.
038: * Results are collected in a report that can finally be
039: * transformed to some external representation.
040: *
041: * @author Søren Bak
042: * @version 1.1 2003/15/2
043: * @since 1.0
044: */
045: public class Report {
046:
047: /** The results collected in the report. */
048: private List results;
049:
050: /** Properties like time, machine, OS, VM, etc. */
051: private Map properties;
052:
053: /**
054: * Creates a new report for benchmark results.
055: */
056: public Report() {
057: results = new ArrayList();
058: properties = new TreeMap();
059: }
060:
061: /**
062: * Adds a result to this report.
063: *
064: * @param result
065: * the result to add.
066: *
067: * @throws NullPointerException
068: * if <tt>result</tt> is <tt>null</tt>.
069: */
070: public void addResult(Result result) {
071: if (result == null)
072: throw new NullPointerException();
073: results.add(result);
074: }
075:
076: /**
077: * Returns the results of this report in no particular
078: * order.
079: *
080: * @return an unmodifiable collection of the results
081: * of this report in no particular order.
082: */
083: public Collection getResults() {
084: return Collections.unmodifiableCollection(results);
085: }
086:
087: /**
088: * Clears the results of this report.
089: */
090: public void clearResults() {
091: results.clear();
092: }
093:
094: /**
095: * Adds a property to this report.
096: *
097: * @param key
098: * the key of the property.
099: *
100: * @param value
101: * the value of the property. If the value is
102: * <tt>null</tt>, the property is removed from
103: * the report.
104: *
105: * @throws NullPointerException
106: * if <tt>key</tt> is <tt>null</tt>.
107: */
108: public void putProperty(String key, String value) {
109: if (key == null)
110: throw new NullPointerException();
111: if (value == null)
112: properties.remove(key);
113: else
114: properties.put(key, value);
115: }
116:
117: /**
118: * Returns a property of this report.
119: *
120: * @param key
121: * the key of the property to return.
122: *
123: * @return the value of the property with the specified
124: * key; returns <tt>null</tt> if no such property
125: * is in this report.
126: *
127: * @throws NullPointerException
128: * if <tt>key</tt> is <tt>null</tt>.
129: */
130: public String getProperty(String key) {
131: if (key == null)
132: throw new NullPointerException();
133: return (String) properties.get(key);
134: }
135:
136: // ---------------------------------------------------------------
137: // Report input/output
138: // ---------------------------------------------------------------
139:
140: private String readLine(Reader in) throws IOException {
141: StringBuffer s = new StringBuffer();
142: int c;
143: while ((c = in.read()) != -1 && c != '\n')
144: s.append((char) c);
145: if (s.length() == 0 && c == -1)
146: return null;
147: return s.toString();
148: }
149:
150: private static String[] split(String s, char c) {
151: ArrayList a = new ArrayList();
152: int p = 0;
153: int len = s.length();
154: while (p < len) {
155: if (a.size() == 0)
156: a.add("");
157: char pc = s.charAt(p);
158: if (pc == c)
159: a.add("");
160: else
161: a
162: .set(a.size() - 1, ((String) a
163: .get(a.size() - 1))
164: + pc);
165: p++;
166: }
167: String[] sa = new String[a.size()];
168: a.toArray(sa);
169: return sa;
170: }
171:
172: /**
173: * Reads results into this report from a specified reader.
174: *
175: * @param in
176: * the reader from which to read results.
177: *
178: * @throws IOException
179: * if an error occurs reading from <tt>out</tt>.
180: */
181: public void readResults(Reader in) throws IOException {
182: String s;
183: int ptr, nptr, len;
184: while ((s = readLine(in)) != null) {
185: String[] fields = split(s, ';');
186: Result result = new Result(fields[0], // benchmark id
187: fields[1], // data set id
188: fields[2], // class id
189: fields[3], // task id
190: fields[4], // task description
191: Long.parseLong(fields[5]) // time
192: );
193: addResult(result);
194: }
195: }
196:
197: /**
198: * Writes the results of this report to a specified writer.
199: *
200: * @param out
201: * the writer on which to write the results.
202: *
203: * @throws IOException
204: * if an error occurs writing to <tt>out</tt>.
205: */
206: public void writeResults(Writer out) throws IOException {
207: Iterator i = results.iterator();
208: while (i.hasNext()) {
209: Result result = (Result) i.next();
210: out.write(result.getBenchmarkId());
211: out.write(';');
212: out.write(result.getDataSetId());
213: out.write(';');
214: out.write(result.getClassId());
215: out.write(';');
216: out.write(result.getTaskId());
217: out.write(';');
218: out.write(result.getTaskDescription());
219: out.write(';');
220: out.write(String.valueOf(result.getTime()));
221: out.write('\n');
222: }
223: }
224:
225: // ---------------------------------------------------------------
226: // Formatting
227: // ---------------------------------------------------------------
228:
229: private static String stylesheet = "body {\n"
230: + " margin-left: 2em;\n" + " margin-right: 2em;\n"
231: + "}\n" + "\n" + "h1, h2, h3, caption, th {\n"
232: + " font-family: helvetica, arial, verdana;\n" + "}\n"
233: + "\n" + "h1 {\n" + " font-size: 24pt;\n"
234: + " font-weight: bold;\n" + "}\n" + "\n" + "h2 {\n"
235: + " font-size: 16pt;\n" + "}\n" + "\n" + "thead {\n"
236: + " background-color: #CCCCFF;\n" + "}\n" + "";
237:
238: /**
239: * Formats this report as HTML on a specified writer.
240: *
241: * @param out
242: * the writer on which to format this report.
243: *
244: * @throws NullPointerException
245: * if <tt>out</tt> is <tt>null</tt>.
246: *
247: * @throws IOException
248: * if an error occurs writing to <tt>out</tt>.
249: */
250: public void writeHTML(Writer out) throws IOException {
251:
252: Set sortedResults = new TreeSet(new ResultComparator());
253: sortedResults.addAll(results);
254: String title = "PCJ Benchmark Results";
255: if (getProperty("report.title") != null)
256: title += " - " + getProperty("report.title");
257:
258: out
259: .write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n");
260: out.write("\"http://www.w3.org/TR/html4/strict.dtd\">\n");
261: out.write("<html lang=\"en\">\n");
262:
263: out.write("<head>\n");
264: out.write(" <title>" + title + "</title>\n");
265: out.write(" <style>\n");
266: out.write(stylesheet);
267: out.write(" </style>\n");
268: out.write("</head>\n");
269:
270: out.write("<body>\n");
271: out.write("<h1>" + title + "</h1>\n");
272:
273: out
274: .write("<table frame=\"border\" rules=\"groups\" cellspacing=\"0\" cellpadding=\"4\">\n");
275: Iterator i = properties.entrySet().iterator();
276: out.write(" <thead>\n");
277: out.write(" <tr>\n");
278: out.write(" ");
279: out.write("<th>Property</th>");
280: out.write("<th>Value</th>\n");
281: out.write(" </tr>\n");
282: out.write(" </thead>\n");
283: out.write(" <tbody>\n");
284: while (i.hasNext()) {
285: Map.Entry e = (Map.Entry) i.next();
286: String s = String.valueOf(e.getKey());
287: out.write(" <tr>\n");
288: out.write(" ");
289: out.write("<td align=\"left\">"
290: + String.valueOf(e.getKey()) + "</td>");
291: out.write("<td align=\"left\">"
292: + String.valueOf(e.getValue()) + "</td>");
293: out.write("\n");
294: out.write(" </tr>\n");
295: }
296: out.write(" </tbody>\n");
297: out.write("</table>\n");
298:
299: String lastBenchmarkId = null;
300: String lastClassId = null;
301: String lastTaskId = null;
302: String lastTaskDescription = null;
303: boolean firstClass = true;
304: boolean firstTask = true;
305:
306: Iterator ri = sortedResults.iterator();
307: while (ri.hasNext()) {
308: Result r = (Result) ri.next();
309:
310: if (!r.getClassId().equals(lastClassId)) {
311: if (!firstClass) {
312: out.write(" </tbody>\n");
313: out.write("</table>\n");
314: }
315: if (!r.getBenchmarkId().equals(lastBenchmarkId)) {
316: out.write("<h1>Benchmark: " + r.getBenchmarkId()
317: + "</h1>\n");
318: }
319: String cid = r.getClassId();
320: String link;
321: if (cid.startsWith("bak.pcj.")) {
322: String url = "../api/" + cid.replace('.', '/')
323: + ".html";
324: link = "<a target=\"_blank\" href=\"" + url
325: + "\" title=\"API: " + cid + "\">" + cid
326: + "</a>";
327: } else if (cid.startsWith("java.")) {
328: String url = "http://java.sun.com/j2se/1.4/docs/api/"
329: + cid.replace('.', '/') + ".html";
330: link = "<a target=\"_blank\" href=\"" + url
331: + "\" title=\"API: " + cid + "\">" + cid
332: + "</a>";
333: } else
334: link = cid;
335: out.write("<h2>Class: " + link + "</h2>\n");
336: out
337: .write("<table frame=\"border\" rules=\"groups\" cellspacing=\"0\" cellpadding=\"4\">\n");
338:
339: out.write(" <thead>\n");
340: out.write(" <tr>\n");
341: out.write(" ");
342: out.write("<th>Task</th>");
343: out.write("<th>Description</th>");
344: out.write("<th>Data set</th>");
345: out.write("<th>Time (ms)</th>");
346: out.write("\n");
347: out.write(" </tr>\n");
348: out.write(" </thead>\n");
349: firstTask = true;
350: } else {
351: if (!r.getBenchmarkId().equals(lastBenchmarkId)) {
352: out.write("<h1>Benchmark: " + r.getBenchmarkId()
353: + "</h1>\n");
354: }
355: }
356:
357: String taskIdHeading;
358: if (!r.getTaskId().equals(lastTaskId)) {
359: taskIdHeading = r.getTaskId();
360: if (!firstTask)
361: out.write(" </tbody>\n");
362: out.write(" <tbody>\n");
363: } else {
364: taskIdHeading = "";
365: }
366:
367: String taskDescription;
368: if (!r.getTaskDescription().equals(lastTaskDescription))
369: taskDescription = r.getTaskDescription();
370: else
371: taskDescription = "";
372:
373: String dataSetIdHeading = r.getDataSetId();
374:
375: out.write(" <tr>\n");
376: out.write(" ");
377: out.write("<td align=\"left\" valign=\"top\">"
378: + taskIdHeading + "</td>");
379: out.write("<td align=\"left\" valign=\"top\">"
380: + taskDescription + "</td>");
381: out.write("<td align=\"left\" valign=\"top\">"
382: + dataSetIdHeading + "</td>");
383: out.write("<td align=\"right\" valign=\"top\">"
384: + String.valueOf(r.getTime()) + "</td>");
385: out.write("\n");
386: out.write(" </tr>\n");
387:
388: lastBenchmarkId = r.getBenchmarkId();
389: lastClassId = r.getClassId();
390: lastTaskId = r.getTaskId();
391: lastTaskDescription = r.getTaskDescription();
392: firstClass = false;
393: firstTask = false;
394: }
395: out.write(" </tbody>\n");
396: out.write("</table>\n");
397: out.write("</body>\n");
398: out.write("</html>\n");
399: }
400:
401: }
|