package perf; public class ManualCharAccessTest { protected int hash; protected final static byte[] SMALL_BYTE_CODES = new byte[256]; protected final static int[] SMALL_INT_CODES = new int[256]; protected final static int[] INT_CODES = new int[0x10000]; protected final static byte[] BYTE_CODES = new byte[0x10000]; static { for (int i = 0; i < 32; ++i) { if (!(i == '\r' || i == '\n' || i == '\t')) { INT_CODES[i] = 1; BYTE_CODES[i] = 1; SMALL_BYTE_CODES[i] = 1; SMALL_INT_CODES[i] = 1; } } INT_CODES['\\'] = 2; BYTE_CODES['\\'] = 2; SMALL_BYTE_CODES['\\'] = 2; SMALL_INT_CODES['\\'] = 2; } protected String generateString(int len) { int counter = 0; StringBuilder sb = new StringBuilder(len + 20); do { sb.append("Some stuff: ").append(len).append("\n"); if ((++counter % 31) == 0) { sb.append("\\"); } } while (sb.length() < len); return sb.toString(); } private void test() throws Exception { final String INPUT_STR = generateString(23000); final char[] INPUT_CHARS = INPUT_STR.toCharArray(); final char[] OUTPUT = new char[INPUT_CHARS.length]; // Let's try to guestimate suitable size, N megs of output final int REPS = (int) ((double) (80 * 1000 * 1000) / (double) INPUT_CHARS.length); System.out.printf("%d bytes to scan, will do %d repetitions\n", INPUT_CHARS.length, REPS); int i = 0; int roundsDone = 0; final int TYPES = 3; final int WARMUP_ROUNDS = 5; final long[] times = new long[TYPES]; while (true) { int round = (i++ % TYPES); String msg; boolean lf = (round == 0); long msecs; switch (round) { case 0: msg = "Read classic"; msecs = readClassic(REPS, INPUT_CHARS, OUTPUT); break; case 1: msg = "Read, byte[]"; msecs = readWithByte(REPS, INPUT_CHARS, OUTPUT); break; case 2: msg = "Read, int[]"; msecs = readWithInt(REPS, INPUT_CHARS, OUTPUT); break; default: throw new Error(); } // skip first 5 rounds to let results stabilize if (roundsDone >= WARMUP_ROUNDS) { times[round] += msecs; } System.out.printf("Test '%s' [hash: 0x%s] -> %d msecs\n", msg, this.hash, msecs); if (lf) { ++roundsDone; if ((roundsDone % 7) == 0 && roundsDone > WARMUP_ROUNDS) { double den = (double) (roundsDone - WARMUP_ROUNDS); System.out.printf("Averages after %d rounds (classic, byte[], int[]): " +"%.1f / %.1f / %.1f msecs\n", (int) den ,times[0] / den, times[1] / den, times[2] / den ); } System.out.println(); } if ((i % 17) == 0) { System.out.println("[GC]"); Thread.sleep(100L); System.gc(); Thread.sleep(100L); } } } private final long readClassic(int REPS, char[] input, char[] output) throws Exception { long start = System.currentTimeMillis(); final byte[] codes = SMALL_BYTE_CODES; final int MAX = 256; while (--REPS >= 0) { int outPtr = 0; for (int i = 0, end = input.length; i < end; ++i) { int ch = input[i]; if (ch < MAX && codes[ch] == NULL_BYTE) { output[outPtr++] = (char) ch; continue; } if (ch == '\\') { output[outPtr++] = '_'; } else if (ch == '\n') { output[outPtr++] = '_'; } } } long time = System.currentTimeMillis() - start; return time; } private final long readWithByte(int REPS, char[] input, char[] output) throws Exception { long start = System.currentTimeMillis(); final byte[] codes = BYTE_CODES; while (--REPS >= 0) { int outPtr = 0; for (int i = 0, end = input.length; i < end; ++i) { char ch = input[i]; if (codes[ch] == NULL_BYTE) { output[outPtr++] = ch; continue; } if (ch == '\\') { output[outPtr++] = '_'; } else if (ch == '\n') { output[outPtr++] = '_'; } } } long time = System.currentTimeMillis() - start; return time; } final static byte NULL_BYTE = (byte) 0; private final long readWithInt(int REPS, char[] input, char[] output) throws Exception { long start = System.currentTimeMillis(); final int[] codes = INT_CODES; while (--REPS >= 0) { int outPtr = 0; for (int i = 0, end = input.length; i < end; ++i) { char ch = input[i]; if (codes[ch] == 0) { output[outPtr++] = ch; continue; } if (ch == '\\') { output[outPtr++] = '_'; } else if (ch == '\n') { output[outPtr++] = '_'; } } } long time = System.currentTimeMillis() - start; return time; } public static void main(String[] args) throws Exception { if (args.length != 0) { System.err.println("Usage: java ..."); System.exit(1); } new ManualCharAccessTest().test(); } }