/** * A simple benchmark that compares the speed of packing integers into longs * with the creation of objects for the purpose of returning integer pairs * from a method. * * This source code is in the public domain. * * @author Tom Gibara */ public class TestCoordinateSpeed { /** * Inner class that simply records its coordinate fields. * */ private static class Point { final int x; final int y; Point(int x, int y) { this.x = x; this.y = y; } } // static long methods /** * Combines a pair of integers into a single long * * @param x the x coordinate * @param y the y coordinate * @return a long which encodes both integers */ private static long point(int x, int y) { return (((long)x) << 32) | y; } /** * Extracts the x coordinate from a point long * @param point the point as a long * @return the x coordinate of the point */ private static int x(long point) { return (int)(point >> 32); } /** * Extracts the y coordinate from a point long * @param point the point as a long * @return the y coordinate of the point */ private static int y(long point) { return (int) point; } // static fields /** * The number of coordinates in the benchmark. * Note that iterations will vary with the square of this number. */ private static int MAX = 10000; /** The number of times the benchmark should run. */ private static int RUNS = 10; // static methods /** Runs the benchmark.*/ public static void main(String[] args) { for(int i = 0; i < RUNS; i++) { testRun(); Thread.yield(); } } /** Performs a test run. */ private static void testRun() { Timing noopTiming = new Timing(); testNoop(MAX); System.out.println("Time for " + MAX*MAX + " noops: " + noopTiming); Timing objectTiming = new Timing(); testObject(MAX); System.out.println("Time for " + MAX*MAX + " objects: " + objectTiming); Timing longTiming = new Timing(); testLong(MAX); System.out.println("Time for " + MAX*MAX + " longs: " + longTiming); } private static void testNoop(int max) { for (int y = 0; y < max; y++) { for (int x = 0; x < max; x++) { x = x; y = y; } } } private static void testObject(int max) { for (int y = 0; y < max; y++) { for (int x = 0; x < max; x++) { Point point = new Point(x, y); x = point.x; y = point.y; } } } private static void testLong(int max) { for (int y = 0; y < max; y++) { for (int x = 0; x < max; x++) { long point = point(x,y); x = x(point); y = y(point); } } } // other inner classes /** * A utility class for timing and display. * Packaged as an inner class for convenience. */ private static class Timing { private static final long MILLIS = 1; private static final long SECOND = 1000; private static final long MINUTE = SECOND * 60; private static final long HOUR = MINUTE * 60; private static final long DAY = HOUR * 24; private long start = System.currentTimeMillis(); private long stop = -1; public void stop() { if (stop == -1) { stop = System.currentTimeMillis(); } else { throw new IllegalStateException("Already stopped."); } } public long getTime() { return now() - start; } public String toString() { long time = getTime(); String postfix = " (" + time +")"; int day = (int) (time / DAY); time -= day * DAY; int hour = (int) (time / HOUR); time -= hour * HOUR; int minute = (int) (time / MINUTE); time -= minute * MINUTE; int second = (int) (time / SECOND); time -= second * SECOND; int millis = (int) (time / MILLIS); boolean force = false; StringBuffer sb = new StringBuffer(); if (day != 0 || force) { if (force) sb.append(" "); sb.append(day).append(" days"); force = true; } if (hour != 0 || force) { if (force) sb.append(" "); sb.append(hour).append("h"); force = true; } if (minute != 0 || force) { if (force) sb.append(" "); sb.append(minute).append("m"); force = true; } if (second != 0 || force) { if (force) sb.append(" "); sb.append(second).append("s"); force = true; } if (force) sb.append(" "); sb.append(millis).append("ms"); force = true; sb.append(postfix); return sb.toString(); } private long now() { long finish = stop == -1 ? System.currentTimeMillis() : stop; return finish; } } }