package timingexp;

import java.io.*;
import java.net.*;
import java.rmi.*;
import Tools.*;

/**
 * Get some rough estimates on overheads of Java for ``performance of
 * name resolution'' thesis section ({@tex \ref{naming_performance}).
 */
public class TestJavaOverheads {

	public static void main(String args[]) {
		Options opts = new Options(args) {
			public void defineOptions() {
				defineOption("off", "first expNum", "9");
				defineOption("conf", "configuration description",
					System.getProperties().getProperty("java.compiler"));
			}
		};
		(new TestJavaOverheads(opts)).realMain();
	}

	Options opts;
	int expNum;
	TestJavaOverheads(Options opts) {
		this.opts = opts;
		expNum = opts.getInt("off")-1;
	}

	void startExp(String desc) {
		expNum++;
		System.out.println("EXP "+expNum+" experimentID "+expNum);
		System.out.println("EXP "+expNum+" desc "+desc);
		System.out.println("EXP "+expNum+" conf "+opts.get("conf"));
	}

	public void realMain() {
		Timer timer;
		int timing, rep, rc;
		int numberOfTimings=10;
		int numberOfReps=1000000;

		startExp("jEmptyLoop");
		for (timing=0; timing<numberOfTimings; timing++) {
			timer = new Timer();
			for (rep=0; rep<numberOfReps; rep++) {
			}
			dumpTimer(timer, numberOfReps);
		}

		startExp("jNullMethod");
		for (timing=0; timing<numberOfTimings; timing++) {
			timer = new Timer();
			for (rep=0; rep<numberOfReps; rep++) {
				rc = nullMethod();
			}
			dumpTimer(timer, numberOfReps);
		}

		// serialize ... your hair!
		numberOfReps = 1000;
		startExp("jSerialize");
		for (timing=0; timing<numberOfTimings; timing++) {
			try {
				Integer myInt = new Integer(-7);
				byte[] ba;
				timer = new Timer();
				for (rep=0; rep<numberOfReps; rep++) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ObjectOutputStream oos = new ObjectOutputStream(baos);
					oos.writeObject(myInt);
					ba = baos.toByteArray();
				}
				dumpTimer(timer, numberOfReps);
			} catch (IOException ex) {
				System.err.println("bummer. "+ex);
			}
		}

		// null RMI call
		try {
			NullRMICall localNull = new NullRMICallImpl();
			String url =
				"//"+InetAddress.getLocalHost().getHostName()+"/NullRMICall";
			Naming.rebind(url, localNull);
			NullRMICall remoteNull = (NullRMICall) Naming.lookup(url);
			Object ro;
	
			numberOfReps = 1000000;
			startExp("jLocalRemoteObj");
			for (timing=0; timing<numberOfTimings; timing++) {
				timer = new Timer();
				for (rep=0; rep<numberOfReps; rep++) {
					ro = localNull.nullMethod();
				}
				dumpTimer(timer, numberOfReps);
			}
	
			numberOfReps = 1000;
			startExp("jRemoteObj");
			for (timing=0; timing<numberOfTimings; timing++) {
				timer = new Timer();
				for (rep=0; rep<numberOfReps; rep++) {
					ro = remoteNull.nullMethod();
				}
				dumpTimer(timer, numberOfReps);
			}
		} catch (Exception ex) {
			System.err.println("bummer. "+ex);
		}

		System.exit(0);
	}

	int nullMethod() {
		return -7;
	}

	void dumpTimer(Timer timer, int numberOfReps) {
		double time = timer.wallTime();
		System.out.println(expNum
			+" "+numberOfReps
			+" "+time
			+" "+((int)(
				time*1000.0/((double) numberOfReps)
				))
			);
	}
}
