/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.test.java;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
/**
* Compare performance of different ways to write and read long[] from a byte-buffer. This is
* for example used when reading and writing index pages.
*
* Result for byte[]: The difference is quite small and almost negligible, writing 100.000 pages
* takes 0.x second. Interestingly, the writing gets a lot slower when using a direct buffer and
* loop based writing (buf.put(byte);), but still is just 0.1 secs.
* -> use array based read/write
*
* For int[], it's different, here loop-based is 1.5x/4x times faster (write/read) than array based.
*
* Longs also do perform like ints, even though we don't have to create a temporary array.
*
* For real world perf, it should be considered that loop based also always checks (autoPaging),
* but that check should be fast.
*
*
* @author Tilmann Zaeschke
*/
public class PerfByteArrayReadWrite {
private static final int MAX_J = 100000;
private static final int MAX_N = 500;
//use multiple arrays to avoid moving 'new byte[]' outside loop
private static final int N_ARRAY = 8;
private static final long[][] allValues = new long[N_ARRAY][MAX_N];
private static final ByteBuffer buf = ByteBuffer.allocateDirect(MAX_N*8);
private boolean autoPaging = false;
public static void main(String[] args) {
for (int j = 0; j < N_ARRAY; j++) {
for (int i = 0; i < allValues[j].length; i++) {
allValues[j][i] = i%200;
}
}
new PerfByteArrayReadWrite().run();
}
private void run() {
writeByte();
writeByte();
writeByte();
writeByte();
writeInt();
writeInt();
writeInt();
writeInt();
writeLong();
writeLong();
writeLong();
writeLong();
readByte();
readByte();
readByte();
readByte();
readInt();
readInt();
readInt();
readInt();
readLong();
readLong();
readLong();
readLong();
}
private void writeByte() {
start("write b array");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
byte[] ba = new byte[values.length];
for (int i = 0; i < values.length; i++) {
ba[i] = (byte) values[i];
}
buf.put(ba);
buf.rewind();
}
autoPaging = true;
stop("write b array");
start("write b loop");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
checkPos(4);
buf.put((byte) values[i]);
}
buf.rewind();
}
autoPaging = true;
stop("write b loop");
}
private void writeInt() {
start("write i array");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
int[] ba = new int[values.length];
for (int i = 0; i < values.length; i++) {
ba[i] = (byte) values[i];
}
IntBuffer lb = buf.asIntBuffer();
lb.put(ba);
buf.position(buf.position() + 4 * ba.length);
buf.rewind();
}
autoPaging = true;
stop("write i array");
start("write i loop");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
checkPos(4);
buf.putInt((int) values[i]);
}
buf.rewind();
}
autoPaging = true;
stop("write i loop");
}
private void writeLong() {
start("write l array");
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
LongBuffer lb = buf.asLongBuffer();
lb.put(values);
buf.position(buf.position() + 8 * values.length);
buf.rewind();
}
stop("write l array");
start("write l loop");
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
buf.putLong(values[i]);
}
buf.rewind();
}
stop("write l loop");
}
private void readByte() {
start("read b array");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
byte[] ba = new byte[values.length];
buf.get(ba);
for (int i = 0; i < values.length; i++) {
values[i] = ba[i];
}
buf.rewind();
}
autoPaging = true;
stop("read b array");
start("read b loop");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
checkPos(4);
values[i] = buf.get();
}
buf.rewind();
}
autoPaging = true;
stop("read b loop");
}
private void readInt() {
start("read i array");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
int[] ba = new int[values.length];
IntBuffer lb = buf.asIntBuffer();
lb.get(ba);
buf.position(buf.position() + 4 * ba.length);
for (int i = 0; i < values.length; i++) {
values[i] = ba[i];
}
buf.rewind();
}
autoPaging = true;
stop("read i array");
start("read i loop");
autoPaging = false;
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
checkPos(4);
values[i] = buf.getInt();
}
buf.rewind();
}
autoPaging = true;
stop("read i loop");
}
private void readLong() {
start("read l array");
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
LongBuffer lb = buf.asLongBuffer();
lb.get(values);
buf.position(buf.position() + 8 * values.length);
buf.rewind();
}
stop("read l array");
start("read l loop");
for (int j = 0; j < MAX_J; j++) {
long[] values = allValues[j%N_ARRAY];
for (int i = 0; i < values.length; i++) {
values[i] = buf.getLong();
}
buf.rewind();
}
stop("read l loop");
}
private boolean checkPos(int l) {
if (autoPaging) {
throw new RuntimeException("" + l);
}
return autoPaging;
}
private long time;
private void start(String msg) {
time = System.currentTimeMillis();
}
private void stop(String msg) {
long t = System.currentTimeMillis() - time;
double td = t/1000.0;
System.out.println(msg + ": " + td);
}
}