/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.tests;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.tests.utils.GdxTest;
import com.badlogic.gdx.utils.BufferUtils;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.TimeUtils;
public class BufferUtilsTest extends GdxTest {
static final int NUM_MB = 5;
@Override
public void create () {
//Not emulated in gwt
//ByteBuffer bytebuffer = BufferUtils.newUnsafeByteBuffer(1000 * 1000);
//BufferUtils.disposeUnsafeByteBuffer(bytebuffer);
ByteBuffer bb = BufferUtils.newByteBuffer(8);
CharBuffer cb = BufferUtils.newCharBuffer(8);
ShortBuffer sb = BufferUtils.newShortBuffer(8);
IntBuffer ib = BufferUtils.newIntBuffer(8);
LongBuffer lb = BufferUtils.newLongBuffer(8);
FloatBuffer fb = BufferUtils.newFloatBuffer(8);
DoubleBuffer db = BufferUtils.newDoubleBuffer(8);
bb.position(4);
BufferUtils.copy(new byte[] {1, 2, 3, 4}, 0, bb, 4);
checkInt(bb.get(), 1);
checkInt(bb.get(), 2);
checkInt(bb.get(), 3);
checkInt(bb.get(), 4);
cb.position(4);
BufferUtils.copy(new char[] {1, 2, 3, 4}, 0, cb, 4);
checkInt(cb.get(), 1);
checkInt(cb.get(), 2);
checkInt(cb.get(), 3);
checkInt(cb.get(), 4);
cb.position(0);
BufferUtils.copy(new char[] {5, 6, 7, 8}, 1, cb, 3);
checkInt(cb.get(), 6);
checkInt(cb.get(), 7);
checkInt(cb.get(), 8);
sb.position(4);
BufferUtils.copy(new short[] {1, 2, 3, 4}, 0, sb, 4);
checkInt(sb.get(), 1);
checkInt(sb.get(), 2);
checkInt(sb.get(), 3);
checkInt(sb.get(), 4);
sb.position(0);
BufferUtils.copy(new short[] {5, 6, 7, 8}, 1, sb, 3);
checkInt(sb.get(), 6);
checkInt(sb.get(), 7);
checkInt(sb.get(), 8);
ib.position(4);
BufferUtils.copy(new int[] {1, 2, 3, 4}, 0, ib, 4);
checkInt(ib.get(), 1);
checkInt(ib.get(), 2);
checkInt(ib.get(), 3);
checkInt(ib.get(), 4);
ib.position(0);
BufferUtils.copy(new int[] {5, 6, 7, 8}, 1, ib, 3);
checkInt(ib.get(), 6);
checkInt(ib.get(), 7);
checkInt(ib.get(), 8);
lb.position(4);
BufferUtils.copy(new long[] {1, 2, 3, 4}, 0, lb, 4);
checkInt(lb.get(), 1);
checkInt(lb.get(), 2);
checkInt(lb.get(), 3);
checkInt(lb.get(), 4);
lb.position(0);
BufferUtils.copy(new long[] {5, 6, 7, 8}, 1, lb, 3);
checkInt(lb.get(), 6);
checkInt(lb.get(), 7);
checkInt(lb.get(), 8);
fb.position(4);
BufferUtils.copy(new float[] {1, 2, 3, 4}, 0, fb, 4);
checkFloat(fb.get(), 1);
checkFloat(fb.get(), 2);
checkFloat(fb.get(), 3);
checkFloat(fb.get(), 4);
fb.position(0);
BufferUtils.copy(new float[] {5, 6, 7, 8}, 1, fb, 3);
checkFloat(fb.get(), 6);
checkFloat(fb.get(), 7);
checkFloat(fb.get(), 8);
if (Gdx.app.getType() != ApplicationType.WebGL) { // gwt throws: NYI: Numbers.doubleToRawLongBits
db.position(4);
BufferUtils.copy(new double[] {1, 2, 3, 4}, 0, db, 4);
checkFloat(db.get(), 1);
checkFloat(db.get(), 2);
checkFloat(db.get(), 3);
checkFloat(db.get(), 4);
db.position(0);
BufferUtils.copy(new double[] {5, 6, 7, 8}, 1, db, 3);
checkFloat(db.get(), 6);
checkFloat(db.get(), 7);
checkFloat(db.get(), 8);
}
ByteBuffer bb2 = BufferUtils.newByteBuffer(4);
bb.position(4);
BufferUtils.copy(bb, bb2, 4);
checkInt(bb2.get(), 1);
checkInt(bb2.get(), 2);
checkInt(bb2.get(), 3);
checkInt(bb2.get(), 4);
bench();
}
private void bench () {
benchByte();
benchShort();
benchInt();
benchLong();
benchFloat();
benchDouble();
}
private void benchByte () {
ByteBuffer bb = BufferUtils.newByteBuffer(1024 * 1024);
byte[] bytes = new byte[1024 * 1024];
int len = bytes.length;
final int NUM_MB = 5;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
bb.clear();
for (int i = 0; i < len; i++)
bb.put(bytes[i]);
}
Gdx.app.log("BufferUtilsTest", "ByteBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
bb.clear();
for (int i = 0; i < len; i++)
bb.put(i, bytes[i]);
}
Gdx.app.log("BufferUtilsTest", "ByteBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
bb.clear();
bb.put(bytes);
}
Gdx.app.log("BufferUtilsTest", "ByteBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
bb.clear();
BufferUtils.copy(bytes, 0, bb, len);
}
Gdx.app.log("BufferUtilsTest", "ByteBuffer native bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void benchShort () {
ShortBuffer sb = BufferUtils.newShortBuffer(1024 * 1024 / 2);
short[] shorts = new short[1024 * 1024 / 2];
int len = shorts.length;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
sb.clear();
for (int i = 0; i < len; i++)
sb.put(shorts[i]);
}
Gdx.app.log("BufferUtilsTest", "ShortBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
sb.clear();
for (int i = 0; i < len; i++)
sb.put(i, shorts[i]);
}
Gdx.app.log("BufferUtilsTest", "ShortBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
sb.clear();
sb.put(shorts);
}
Gdx.app.log("BufferUtilsTest", "ShortBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
sb.clear();
BufferUtils.copy(shorts, 0, sb, len);
}
Gdx.app.log("BufferUtilsTest", "ShortBuffer native bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void benchInt () {
IntBuffer ib = BufferUtils.newIntBuffer(1024 * 1024 / 4);
int[] ints = new int[1024 * 1024 / 4];
int len = ints.length;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
ib.clear();
for (int i = 0; i < len; i++)
ib.put(ints[i]);
}
Gdx.app.log("BufferUtilsTest", "IntBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
ib.clear();
for (int i = 0; i < len; i++)
ib.put(i, ints[i]);
}
Gdx.app.log("BufferUtilsTest", "IntBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
ib.clear();
ib.put(ints);
}
Gdx.app.log("BufferUtilsTest", "IntBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
ib.clear();
BufferUtils.copy(ints, 0, ib, len);
}
Gdx.app.log("BufferUtilsTest", "IntBuffer native bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void benchLong () {
LongBuffer lb = BufferUtils.newLongBuffer(1024 * 1024 / 8);
long[] longs = new long[1024 * 1024 / 8];
int len = longs.length;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
lb.clear();
for (int i = 0; i < len; i++)
lb.put(longs[i]);
}
Gdx.app.log("BufferUtilsTest", "LongBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
lb.clear();
for (int i = 0; i < len; i++)
lb.put(i, longs[i]);
}
Gdx.app.log("BufferUtilsTest", "LongBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
lb.clear();
lb.put(longs);
}
Gdx.app.log("BufferUtilsTest", "LongBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
lb.clear();
BufferUtils.copy(longs, 0, lb, len);
}
Gdx.app.log("BufferUtilsTest", "LongBuffer native bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void benchFloat () {
FloatBuffer fb = BufferUtils.newFloatBuffer(1024 * 1024 / 4);
float[] floats = new float[1024 * 1024 / 4];
int len = floats.length;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
fb.clear();
for (int i = 0; i < len; i++)
fb.put(floats[i]);
}
Gdx.app.log("BufferUtilsTest", "FloatBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
fb.clear();
for (int i = 0; i < len; i++)
fb.put(i, floats[i]);
}
Gdx.app.log("BufferUtilsTest", "FloatBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
fb.clear();
fb.put(floats);
}
Gdx.app.log("BufferUtilsTest", "FloatBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
fb.clear();
BufferUtils.copy(floats, 0, fb, len);
}
Gdx.app.log("BufferUtilsTest", "FloatBuffer native bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void benchDouble () {
DoubleBuffer db = BufferUtils.newDoubleBuffer(1024 * 1024 / 8);
double[] doubles = new double[1024 * 1024 / 8];
int len = doubles.length;
// relative put
long start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
db.clear();
for (int i = 0; i < len; i++)
db.put(doubles[i]);
}
Gdx.app.log("BufferUtilsTest", "DoubleBuffer relative put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// absolute put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
db.clear();
for (int i = 0; i < len; i++)
db.put(i, doubles[i]);
}
Gdx.app.log("BufferUtilsTest", "DoubleBuffer absolute put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// bulk put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
db.clear();
db.put(doubles);
}
Gdx.app.log("BufferUtilsTest", "DoubleBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
// JNI put
start = TimeUtils.nanoTime();
for (int j = 0; j < NUM_MB; j++) {
db.clear();
BufferUtils.copy(doubles, 0, db, len);
}
Gdx.app.log("BufferUtilsTest", "DoubleBuffer bulk put: " + (TimeUtils.nanoTime() - start) / 1000000000.0f);
}
private void checkInt (long val1, long val2) {
if (val1 != val2) {
Gdx.app.error("BufferUtilsTest", "checkInt failed: "+val1+" != "+val2);
throw new GdxRuntimeException("Error, val1 != val2");
}
}
private void checkFloat (double val1, double val2) {
if (val1 != val2) {
Gdx.app.error("BufferUtilsTest", "checkFloat failed: "+val1+" != "+val2);
throw new GdxRuntimeException("Error, val1 != val2");
}
}
}