/* This file is part of VoltDB. * Copyright (C) 2008-2009 VoltDB L.L.C. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.*; import java.util.Date; public class Bench { private static native void foo(); private native void bar(long engine, boolean undo, boolean rwset, long fragid, byte[] paramset); private native void bar2(long engine, long fragid, ByteBuffer paramset, int paramlength, ByteBuffer result, int resultcapacity); private native void bar3(long engine, long fragid, ByteBuffer paramset, int paramlength, ByteBuffer result, int resultcapacity); private native byte[] bar3a(long engine, long fragid, byte[] paramset); private native void bar4(long engine, long fragid, ByteBuffer paramset, int paramlength, ByteBuffer result, int resultcapacity); public static void main(String[] args) { for (int trial = 0; trial < 5; ++trial) { // to ignore class loading and JIT cost { System.out.println("foo()"); int count = 1000000; long start = System.nanoTime(); for (int i = 0; i < count; i++) foo(); long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("bar()"); int count = 1000000; Bench bench = new Bench(); byte[] array = new byte[] {}; long start = System.nanoTime(); for (int i = 0; i < count; i++) bench.bar(0L, false, false, 0L, array); long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("bar2()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer params = ByteBuffer.allocateDirect(500); byte[] org = "kljajrlgkjadlkjfglkajdflkgjadlkjgkljdfklgjdfajalksjdlkajskldjlajsdkjaklsjdljaskdjaksjdkajlsd".getBytes(); byte[] buf2 = new byte[org.length]; ByteBuffer result = ByteBuffer.allocateDirect(1000000); long start = System.nanoTime(); for (int i = 0; i < count; i++) { params.clear(); params.put(org); result.clear(); bench.bar2(0L, 0L, params, org.length, result, result.capacity()); result.get(buf2); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("bar3()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer params = ByteBuffer.allocateDirect(500); byte[] org = "kljajrlgkjadlkjfglkajdflkgjadlkjgkljdfklgjdfajalksjdlkajskldjlajsdkjaklsjdljaskdjaksjdkajlsd".getBytes(); byte[] buf2 = new byte[org.length]; ByteBuffer result = ByteBuffer.allocateDirect(1000000); long start = System.nanoTime(); for (int i = 0; i < count / 5; i++) { params.clear(); params.put(org); params.put(org); params.put(org); params.put(org); params.put(org); result.clear(); bench.bar3(0L, 0L, params, org.length, result, result.capacity()); result.get(buf2); result.get(buf2); result.get(buf2); result.get(buf2); result.get(buf2); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("bar3a()"); int count = 1000000; Bench bench = new Bench(); byte[] org = "kljajrlgkjadlkjfglkajdflkgjadlkjgkljdfklgjdfajalksjdlkajskldjlajsdkjaklsjdljaskdjaksjdkajlsd".getBytes(); long start = System.nanoTime(); for (int i = 0; i < count; i++) { byte[] params = (byte[]) org.clone(); byte[] buf2 = bench.bar3a(0L, 0L, params); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("bar4()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer params = ByteBuffer.allocateDirect(500); byte[] org = "kljajrlgkjadlkjfglkajdflkgjadlkjgkljdfklgjdfajalksjdlkajskldjlajsdkjaklsjdljaskdjaksjdkajlsd".getBytes(); byte[] buf2 = new byte[org.length]; ByteBuffer result = ByteBuffer.allocateDirect(1000000); params.clear(); params.put(org); result.clear(); long start = System.nanoTime(); for (int i = 0; i < count; i++) { bench.bar4(0L, 0L, params, org.length, result, result.capacity()); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("10params_direct()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer direct = ByteBuffer.allocateDirect(4096); Object[] params = new Object[]{1L, 2.0d, "asdjhhjh", 4L, 5L, 6.0d, "fgkljdfgljkdfg", 8L, 9L, 10.0d}; long start = System.nanoTime(); for (int i = 0; i < count; i++) { direct.clear(); writeParams(params, direct); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("10params_doublebuffer()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer direct = ByteBuffer.allocateDirect(4096); byte[] heap_bytes = new byte[4096]; ByteBuffer tmp = ByteBuffer.wrap(heap_bytes); Object[] params = new Object[]{1L, 2.0d, "asdjhhjh", 4L, 5L, 6.0d, "fgkljdfgljkdfg", 8L, 9L, 10.0d}; long start = System.nanoTime(); for (int i = 0; i < count; i++) { direct.clear(); tmp.clear(); writeParams(params, tmp); direct.put(heap_bytes, 0, tmp.position()); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } { System.out.println("10params_myown()"); int count = 1000000; Bench bench = new Bench(); ByteBuffer direct = ByteBuffer.allocateDirect(4096); byte[] heap_bytes = new byte[4096]; MyLEHeapBuffer tmp = new MyLEHeapBuffer(heap_bytes); Object[] params = new Object[]{1L, 2.0d, "asdjhhjh", 4L, 5L, 6.0d, "fgkljdfgljkdfg", 8L, 9L, 10.0d}; long start = System.nanoTime(); for (int i = 0; i < count; i++) { direct.clear(); tmp.clear(); writeParams(params, tmp); direct.put(heap_bytes, 0, tmp.position()); } long end = System.nanoTime(); System.out.println(end - start + " ns for " + count + " calls"); System.out.println((((double) end - start) / count) + " ns/call"); } } } static { System.loadLibrary("Bench"); } private static void writeParams(Object[] params, ByteBuffer buffer) { buffer.put((byte) params.length); for (Object obj : params) { if (obj == null) { VoltType type = VoltType.NULL; buffer.put(type.getValue()); continue; } Class<?> cls = obj.getClass(); /* if (cls.isArray()) { // Special case for byte[] -> String if (obj instanceof byte[]) { byte[] b = (byte[]) obj; buffer.putByte(VoltType.STRING.getValue()); buffer.putShort(b.length); buffer.put(b); continue; } buffer.writeByte(ARRAY); VoltType type = VoltType.typeFromClass(cls.getComponentType()); buffer.writeByte(type.getValue()); switch (type) { case INTEGER: buffer.putArray((long[]) obj); break; case FLOAT: buffer.putArray((double[]) obj); break; case STRING: buffer.putArray((String[]) obj); break; case TIMESTAMP: buffer.putArray((Date[]) obj); break; default: throw new RuntimeException("FIXME: Unsupported type " + type); } continue; } */ VoltType type = VoltType.typeFromClass(cls); buffer.put(type.getValue()); switch (type) { case INTEGER: buffer.putLong((Long) obj); break; case FLOAT: buffer.putDouble((Double) obj); break; case STRING: writeString(buffer, ((String) obj)); break; case TIMESTAMP: buffer.putLong(((Date) obj).getTime()); break; } } } private static void writeString(ByteBuffer buffer, String string) { final short NULL_STRING_INDICATOR = -1; if (string == null) { buffer.putShort(NULL_STRING_INDICATOR); return; } // assume not null now int len = string.length(); buffer.putShort((short) len); byte[] strbytes = {}; try { // this will need to be less "western" in the future strbytes = string.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } assert len == strbytes.length; buffer.put(strbytes); } public enum VoltType { INTEGER ((byte)6), FLOAT ((byte)8), TIMESTAMP ((byte)11), STRING ((byte)9), MONEY ((byte)20), VOLTTABLE ((byte)21), INVALID ((byte)0), NULL ((byte)1); private final byte val; VoltType(byte val) { this.val = val; } public byte getValue() { return val; } public static VoltType get(byte val) { for (VoltType type : VoltType.values()) { if (type.val == val) return type; } throw new AssertionError("Unknown type: " + String.valueOf(val)); } public static VoltType typeFromClass(Class<?> cls) { if ((cls == long.class) || (cls == Long.class) || (cls == Integer.class) || (cls == int.class)) return INTEGER; if ((cls == Float.class) || (cls == float.class) || (cls == Double.class) || (cls == double.class)) return FLOAT; if ((cls == Date.class)) return TIMESTAMP; if ((cls == String.class)) return STRING; throw new RuntimeException("Unimplemented Object Type"); } } private static class MyLEHeapBuffer { byte[] bytes; int pos = 0; MyLEHeapBuffer(byte[] bytes) { this.bytes = bytes; } int position() { return pos;} void clear() {pos = 0;} void put(byte[] b) { System.arraycopy(b, 0, bytes, pos, b.length); pos += b.length; } void putByte(byte b) {bytes[pos++] = b;} void putString(String string) { final short NULL_STRING_INDICATOR = -1; if (string == null) { putShort(NULL_STRING_INDICATOR); return; } // assume not null now int len = string.length(); putShort((short) len); byte[] strbytes = {}; try { // this will need to be less "western" in the future strbytes = string.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } assert len == strbytes.length; put(strbytes); } void putShort(short v) { bytes[pos++] = (byte) (v >> 0); bytes[pos++] = (byte) (v >> 8); } void putLong(long v) { bytes[pos++] = (byte) (v >> 0); bytes[pos++] = (byte) (v >> 8); bytes[pos++] = (byte) (v >> 16); bytes[pos++] = (byte) (v >> 24); bytes[pos++] = (byte) (v >> 32); bytes[pos++] = (byte) (v >> 40); bytes[pos++] = (byte) (v >> 48); bytes[pos++] = (byte) (v >> 56); /* which is faster? bytes[pos] = (byte) (v >> 0); bytes[pos+1] = (byte) (v >> 8); bytes[pos+2] = (byte) (v >> 16); bytes[pos+3] = (byte) (v >> 24); bytes[pos+4] = (byte) (v >> 32); bytes[pos+5] = (byte) (v >> 40); bytes[pos+6] = (byte) (v >> 48); bytes[pos+7] = (byte) (v >> 56); pos += 8; */ } void putDouble(double v) { putLong(Double.doubleToRawLongBits(v)); } } private static void writeParams(Object[] params, MyLEHeapBuffer buffer) { buffer.putByte((byte) params.length); for (Object obj : params) { if (obj == null) { VoltType type = VoltType.NULL; buffer.putByte(type.getValue()); continue; } Class<?> cls = obj.getClass(); VoltType type = VoltType.typeFromClass(cls); buffer.putByte(type.getValue()); switch (type) { case INTEGER: buffer.putLong((Long) obj); break; case FLOAT: buffer.putDouble((Double) obj); break; case STRING: buffer.putString((String) obj); break; case TIMESTAMP: buffer.putLong(((Date) obj).getTime()); break; } } } }