001: /*
002: * Copyright (c) 2000-2001 Sosnoski Software Solutions, Inc.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
020: * IN THE SOFTWARE.
021: */
022:
023: package com.sosnoski.xmlbench;
024:
025: import java.io.*;
026:
027: import java.util.*;
028:
029: /**
030: * Base class for XML benchmark tests. This class provides some basic methods
031: * used by the testing. It must be subclassed for each particular parser or
032: * document representation to be tested.
033: *
034: * @author Dennis M. Sosnoski
035: * @version 1.2
036: */
037:
038: public abstract class BenchBase {
039: // Indices for vector of values returned by time test
040: /** Best document build time result index. */
041: public static final int BUILD_MIN_INDEX = 0;
042: /** Average document build time result index. */
043: public static final int BUILD_AVERAGE_INDEX = 1;
044: /** Best document walk time result index. */
045: public static final int WALK_MIN_INDEX = 2;
046: /** Average document walk time result index. */
047: public static final int WALK_AVERAGE_INDEX = 3;
048: /** Best document text generation time result index. */
049: public static final int TEXT_MIN_INDEX = 4;
050: /** Average document text generation time result index. */
051: public static final int TEXT_AVERAGE_INDEX = 5;
052: /** Best serialization time result index. */
053: public static final int SERIALIZE_MIN_INDEX = 6;
054: /** Average serialization time result index. */
055: public static final int SERIALIZE_AVERAGE_INDEX = 7;
056: /** Best unserialization time walk time result index. */
057: public static final int UNSERIALIZE_MIN_INDEX = 8;
058: /** Average unserialization time walk time result index. */
059: public static final int UNSERIALIZE_AVERAGE_INDEX = 9;
060: /** Best modification time result index. */
061: public static final int MODIFY_MIN_INDEX = 10;
062: /** Average modification time result index. */
063: public static final int MODIFY_AVERAGE_INDEX = 11;
064: /** Serialized size result index. */
065: public static final int SERIALIZE_SIZE_INDEX = 12;
066: /** Element count index. */
067: public static final int ELEMENT_COUNT_INDEX = 13;
068: /** Content text segment count index. */
069: public static final int CONTENT_COUNT_INDEX = 14;
070: /** Attribute count index. */
071: public static final int ATTRIBUTE_COUNT_INDEX = 15;
072: /** Text character count index. */
073: public static final int TEXTCHAR_COUNT_INDEX = 16;
074: /** Attribute character count index. */
075: public static final int ATTRCHAR_COUNT_INDEX = 17;
076: /** Count of result values returned. */
077: public static final int TIME_RESULT_COUNT = 18;
078:
079: // Indices for vector of values returned by space test
080: /** Initial memory usage (before document construction). */
081: public static final int INITIAL_MEMORY_INDEX = 0;
082: /** Net change in memory usage from start to end. */
083: public static final int DELTA_MEMORY_INDEX = 1;
084: /** First document memory usage. */
085: public static final int FIRST_SPACE_INDEX = 2;
086: /** Last document memory usage. */
087: public static final int AVERAGE_SPACE_INDEX = 3;
088: /** Memory usage change after walking document. */
089: public static final int WALKED_SPACE_INDEX = 4;
090: /** Count of result values returned. */
091: public static final int SPACE_RESULT_COUNT = 5;
092:
093: /** Abbreviated descriptions of time test result values. */
094: static public final String[] s_timeShortDescriptions = {
095: "Build mn", "Build av", "Walk mn", "Walk av", "Write mn",
096: "Write av", "Ser mn", "Ser av", "Unser mn", "Unser av",
097: "Mod mn", "Mod av", "Ser sz", "Elems", "Conts", "Attrs",
098: "Text ch", "Attr ch" };
099:
100: /** Full descriptions of time test result values. */
101: static public final String[] s_timeFullDescriptions = {
102: "Build document minimum time (ms)",
103: "Build document average time (ms)",
104: "Walk document minimum time (ms)",
105: "Walk document average time (ms)",
106: "Write document text minimum time (ms)",
107: "Write document text average time (ms)",
108: "Serialize document minimum time (ms)",
109: "Serialize document average time (ms)",
110: "Unserialize document minimum time (ms)",
111: "Unserialize document average time (ms)",
112: "Modify document minimum time (ms)",
113: "Modify document average time (ms)",
114: "Serialized document size (bytes)", "Elements in document",
115: "Content text segments in document",
116: "Attributes in document",
117: "Text content characters in document",
118: "Attribute value characters in document" };
119:
120: /** Abbreviated descriptions of space test result values. */
121: static public final String[] s_spaceShortDescriptions = {
122: "Init mem", "Chg mem", "First sz", "Avg sz", "Walked sz" };
123:
124: /** Full descriptions of space test result values. */
125: static public final String[] s_spaceFullDescriptions = {
126: "Initial memory usage before document parse (bytes)",
127: "Net change in memory usage (bytes)",
128: "First document copy memory size (bytes)",
129: "Average document copy memory size (bytes)",
130: "Last walked document memory increase (bytes)" };
131:
132: /** Total interval in milliseconds to wait for garbage collection. */
133: public static final long GARBAGE_COLLECT_DELAY = 1000;
134:
135: /** Interval in milliseconds to wait each time. */
136: public static final long GARBAGE_UNIT_DELAY = 100;
137:
138: /** Memory usage at start of test. */
139: protected static long m_lastMemory;
140:
141: /** Time at start of test. */
142: protected static long m_lastTime;
143:
144: /** Name for this test configuration. */
145: protected final String m_configName;
146:
147: /** Optional variant information for test configuration. */
148: protected String m_configVariant;
149:
150: /** Destination for test results listing. */
151: protected PrintStream m_printStream;
152:
153: /** Flag for printing document summary information. */
154: protected boolean m_printSummary;
155:
156: /** Flag for printing detailed pass results. */
157: protected boolean m_printPass;
158:
159: /**
160: * Constructor.
161: *
162: * @param config test configuration name
163: */
164:
165: protected BenchBase(String config) {
166: m_configName = config;
167: }
168:
169: /**
170: * Initializes the memory state prior to a test run. This method first
171: * requests a garbage collection operation, then waits for a fixed interval
172: * in order to encourage the JVM to do the collection. It also sets the
173: * start of test value for memory usage.
174: */
175:
176: protected void initMemory() {
177: long done = System.currentTimeMillis() + GARBAGE_COLLECT_DELAY;
178: Runtime rt = Runtime.getRuntime();
179: while (System.currentTimeMillis() < done) {
180: rt.gc();
181: try {
182: Thread.sleep(GARBAGE_UNIT_DELAY);
183: } catch (InterruptedException ex) {
184: }
185: }
186: m_lastMemory = rt.totalMemory() - rt.freeMemory();
187: }
188:
189: /**
190: * Initializes the time prior to a test run. This method justs sets the
191: * start of test time from the system clock.
192: */
193:
194: protected void initTime() {
195: m_lastTime = System.currentTimeMillis();
196: }
197:
198: /**
199: * Report a value. Prints the leading text and the value with a space
200: * between, if printing is enabled.
201: *
202: * @param lead leading text for test results
203: * @param value value to be printed
204: */
205:
206: protected void reportValue(String lead, int value) {
207: if (m_printStream != null) {
208: m_printStream.println(" " + lead + ' ' + value);
209: }
210: }
211:
212: /**
213: * Find test pass time. Besides returning the time for the last test pass,
214: * this sets the current time as the start of the next test pass.
215: *
216: * @return milliseconds taken for the test
217: */
218:
219: protected int testPassTime() {
220: long now = System.currentTimeMillis();
221: int time = (int) (now - m_lastTime);
222: m_lastTime = now;
223: return time;
224: }
225:
226: /**
227: * Find test pass space. Besides returning the space for the last test pass,
228: * this sets the current space usage as the start of the next test pass.
229: *
230: * @return bytes of memory added by test pass (negative if space released)
231: */
232:
233: protected int testPassSpace() {
234: long done = System.currentTimeMillis() + GARBAGE_COLLECT_DELAY;
235: while (System.currentTimeMillis() < done) {
236: System.gc();
237: try {
238: Thread.sleep(GARBAGE_UNIT_DELAY);
239: } catch (InterruptedException ex) {
240: }
241: }
242: Runtime rt = Runtime.getRuntime();
243: long used = rt.totalMemory() - rt.freeMemory();
244: long diff = used - m_lastMemory;
245: m_lastMemory = used;
246: return (int) diff;
247: }
248:
249: /**
250: * Report the results of a time test run. Prints the time taken for the
251: * last test and sets the current time as the start time for the next
252: * test.
253: *
254: * @param test test description for display
255: * @return milliseconds taken for the test
256: */
257:
258: protected int reportTime(String test) {
259: int time = testPassTime();
260: if (m_printStream != null) {
261: m_printStream.println(" " + test + " in " + time + " ms.");
262: }
263: return time;
264: }
265:
266: /**
267: * Report the results of a memory test run. First attempts a
268: * garbage collection operation before computing the difference between
269: * the memory in use at the end of the test and that in use at the start
270: * of the test. Prints the space used by the test and sets the current
271: * space as the base for the next test.
272: *
273: * @param test test description for display
274: * @return space used by test
275: */
276:
277: protected int reportSpace(String test) {
278: int space = testPassSpace();
279: if (m_printStream != null) {
280: m_printStream.println(" " + test + " used space " + space);
281: }
282: return space;
283: }
284:
285: /**
286: * Print document summary information. Prints the information with a
287: * supplied lead phrase.
288: *
289: * @param lead lead text phrase for document summary
290: * @param info document summary information
291: * @param print stream on which to print
292: */
293:
294: protected void printSummary(String lead, DocumentSummary info,
295: PrintStream print) {
296: print.println(lead + " has " + info.getElementCount()
297: + " elements, " + info.getAttributeCount()
298: + " attributes with " + info.getAttrCharCount()
299: + " characters of data, and " + info.getContentCount()
300: + " content text segements with "
301: + info.getTextCharCount() + " characters of text");
302: }
303:
304: /**
305: * Get configuration name. Returns the name of the document model used
306: * by this test, with any supplied variant information appended in
307: * parenthesis.
308: *
309: * @return document model name
310: */
311:
312: public String getName() {
313: if (m_configVariant == null) {
314: return m_configName;
315: } else {
316: return m_configName + " (" + m_configVariant + ')';
317: }
318: }
319:
320: /**
321: * Set configuration variant information. This may be used by subclasses
322: * which need to deal with several variations of a single configuration.
323: *
324: * @param variant configuration variant description, appended to name
325: */
326:
327: protected void setVariant(String variant) {
328: m_configVariant = variant;
329: }
330:
331: /**
332: * Set output print stream for printing detailed test run results.
333: *
334: * @param print test results listing destination (<code>null</code> if
335: * no listing output)
336: */
337:
338: public void setPrint(PrintStream print) {
339: m_printStream = print;
340: }
341:
342: /**
343: * Set flag for printing document summary information.
344: *
345: * @param show flag for document summary information to be printed
346: */
347:
348: public void setShowDocument(boolean show) {
349: m_printSummary = show;
350: }
351:
352: /**
353: * Set flag for printing individual test pass results.
354: *
355: * @param show flag for document summary information to be printed
356: */
357:
358: public void setShowPass(boolean show) {
359: m_printPass = show;
360: }
361:
362: /**
363: * Main time test method. This must be implemented by the subclass to
364: * perform the sequence of speed tests appropriate to the test
365: * platform.
366: *
367: * @param passes number of passes of each test
368: * @param excludes number of initialization passes excluded from averages
369: * @param texts document texts for test
370: * @return result times array
371: */
372:
373: public abstract int[] runTimeTest(int passes, int excludes,
374: byte[][] texts);
375:
376: /**
377: * Main space test method. This must be implemented by the subclass to
378: * perform the sequence of space tests appropriate to the test
379: * platform.
380: *
381: * @param passes number of passes of each test
382: * @param excludes number of initialization passes excluded from averages
383: * @param texts document texts for test
384: * @return result spaces array
385: */
386:
387: public abstract int[] runSpaceTest(int passes, int excludes,
388: byte[][] texts);
389: }
|