// perftest.java

import Byte;
import ByteArray;

class perftest {

	public static void main(String[] argv) throws ArrayIndexOutOfBoundsException {
		long start, time;

		System.out.print("\t");
		for (int n = 0; n < 9; n++)
			System.out.print("Test " + n + (n < 8 ? "\t" : "\n"));

		for (int n = 0; n < 10; n++) {
		
			System.out.print("Trial " + n + "\t");

			//Test 0

			//A vector of Byte wrapper objects is used to
			//maintain an expanding byte array.  The Byte
			//wrapper class is defined in this file, since
			//it is not part of the JDK until version 1.1.
			//One new vector is allocated per extension
			//round, and one new vector is allocated per
			//test round.

			start = System.currentTimeMillis();
			for (int i = 0; i < 10; i++) {
				java.util.Vector data = new java.util.Vector(200);
				data.setSize(1);
				data.setElementAt(new Byte(0), 0);
				for (int j = 0; j < 200; j++) {
					java.util.Vector data2 = new java.util.Vector(201);
					data2.setSize(data.size() + 1);
					data2.setElementAt(new Byte(0), 0);
					for (int k = 0; k < data.size(); k++)
						data2.setElementAt(data.elementAt(k), k + 1);
					data = data2;
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 1

			//A byte array is extended byte-by-byte by allocating
			//a new array one byte larger and copying the contents
			//of the existing array to the end of the new array.
			//Then the reference to the old array is replaced with
			//a reference to the new array so that the old array is
			//offered up for garbage colledtion. Copying is done
			//using an explicit for loop.  One new byte array object
			//is created per extension round.

			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				byte[] data = new byte[1];
				for (int j = 0; j < 200; j++) {
					byte[] data2 = new byte[data.length + 1];
					for (int k = 0; k < data.length; k++)
						data2[k + 1] = data[k];
					data = data2;
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 2

			//A byte array is extended byte-by-byte by allocating
			//a new array one byte larger and copying the contents
			//of the existing array to the end of the new array.
			//Then the reference to the old array is replaced with
			//a reference to the new array so that the old array is
			//offered up for garbage colledtion. Copying is done
			//using the System.arraycopy utility function.  One new
			//byte array object is created per extension round,
			//and one new byte array is created per test round.

			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				byte[] data = new byte[1];
				for (int j = 0; j < 200; j++) {
					byte[] data2 = new byte[data.length + 1];
					System.arraycopy(data, 0, data2, 1, data.length);
					data = data2;
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 3

			//In this test two byte arrays are pre-allocated
			//with the necessary space and progressive copies
			//are done between the arrays with an explicit for
			//loop.  Two new byte arrays are created per test
			//round.

			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				byte[] data = new byte[200];
				byte[] data2 = new byte[201];
				for (int j = 1; j < 201; j++)
					for (int k = 0; k < data.length - j; k++)
						data2[k + 1] = data[k];
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 4

			//In this test two byte arrays are pre-allocated
			//with the necessary space and progressive copies
			//are done between the arrays using the System
			//arraycopy method.  Two new byte arrays are created
			//per test round.

			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				byte[] data = new byte[200];
				byte[] data2 = new byte[201];
				for (int j = 1; j < 201; j++)
					System.arraycopy(data, data.length - j, data2, 1, j);
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 5

			//In this test two byte arrays are pre-allocated
			//with the necessary space and progressive copies
			//are done between the arrays using the System
			//arraycopy method.  Two new byte arrays are created
			//in advance, so none are created during the test
			//rounds.

			byte[] data3 = new byte[200];
			byte[] data4 = new byte[201];
			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				for (int j = 1; j < 201; j++)
					System.arraycopy(data3, 200 - j, data4, 1, j);
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 6

			//This test uses a ByteArray class that acts like a
			//vector, except that it does not incur the overhead
			//of maintaining references to contained objects.
			//ByteArray doubles in size each time it runs out
			//of room.  In this case, however, the ByteArray is
			//primed in advance to hold as many characters as
			//necessary.

			ByteArray b = null;
			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				b = new ByteArray(201);
				b.append('b');
				for (int j = 0; j < 200; j++) {
					b.prepend('c');
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");

			//Test 7

			//This test is the same as 6 except that the
			//ByteArray prependWrapper method is called
			//instead of the prepend method.  prependWrapper
			//attempts to reduce lines of code in the class
			//by allocating a temporary byte array for the
			//integer argument, instead of having an explicit
			//method to deal with prepending an integer value.
			
			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				b = new ByteArray(201);
				b.append('b');
				for (int j = 0; j < 200; j++) {
					b.prependWrapper('c');
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\t");


			//Test 8

			//In this test a ByteArrayOutputStream is used
			//to contain the growing byte array.  However,
			//ByteArrayOutputStream only allows appending
			//to the end.  So this test does not reflect
			//the same goal as the preceeding tests.

			java.io.ByteArrayOutputStream baos;
			start = System.currentTimeMillis();
			for (int i = 0; i < 1000; i++) {
				baos = new java.io.ByteArrayOutputStream(201);
				baos.write('b');
				for (int j = 0; j < 200; j++) {
					baos.write('c');
				}
			}
			time = System.currentTimeMillis();
			System.out.print((time - start) + "\n");

			/*
			//Test code to dump and verify a ByteArray
			System.out.print("b: [");
			for (int i = 0; i < b.size(); i++)
				System.out.print((char)(b.data()[i]));
			System.out.print("]\n");
			System.out.println("start: " + b.start());
			System.out.println("length: " + b.length());
			System.out.println("size: " + b.size());

			byte[] d = b.getBytes();
			System.out.print("\nd: [");
			for (int i = 0; i < d.length; i++)
				System.out.print((char)d[i]);
			System.out.print("]\n");
			System.out.println("length: " + d.length);
			*/
		}
	}

}
