This library supports creating arrays-of-structs in Java
Main features:
[x] support for MappedObject (structs) and MappedObjectArray (array-of structs)
[x] optional bounds checking for MappedObjectArray
[x] excellent performance (even for query methods like .sizeof(), .stride(), .elements(), etc)
[x] grouped/nested structs: interleaving mapped object arrays using strides and offsets
[x] verifies configurations ahead of time: exceptions, no native crashes
[x] allows both JIT and AOT bytecode transformation (just add JAR to classpath)
[x] no runtime reliance on bytecode transformation, allowing future Dalvik/Android support
General notice:
[x] don’t expect huge performance gains per se: memory access is about as fast as field access, albeit with less cache-misses
[x] the biggest speedup will be caused by no longer having to copy data back and forth between instances and buffers
I might elaborate later on this subject, but for now I expect the code to speak for itself…
Example of mapped Vec3:
public class Vec3 {
public float x;
public float y;
public float z;
}
ByteBuffer bb = ...;
Vec3 mapped = new Vec3(bb);
mapped.x = 1f;
mapped.y = 0f;
mapped.z = 2f;
mapped.index(2); // slides mapped object to 3rd Vec3
mapped.x = 7f;
mapped.y = 4f;
mapped.z = 5f;
for(int i=0; i<mapped.elements(); i++) {
mapped.index(i);
// ...
}
[x][y][z][x][y][z][x][y][z][x][y][z] -->
^ ^ ^ ^
1f,0f,2f 7f,4f,5f
mapped.stride(mapped.sizeof() + 4);
[x][y][z][?][x][y][z][?][x][y][z][?][x][y][z][?] -->
^ ^ ^ ^
Example of nested mapped object {Vec3,Vec3,Vec2}:
public static class VNC {
public Vec3 vertex;
public Vec3 normal;
public Vec2 texcoord;
}
VNC vnc = new VNC(bb); // sets the stride of 'vertex', 'normal', 'texcoord'
vnc.normal.z = 0.13f;
vnc.index(13); // sets the index of 'vertex', 'normal', 'texcoord'
vnc.normal.z = 0.14f;
Demo code that actually works: (shipped with JAR)
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import net.indiespot.mapped.MappedObject;
import net.indiespot.mapped.MappedObjectArray;
import net.indiespot.mapped.MappedObjectBuilder;
import net.indiespot.mapped.MappedObjectFactory;
import net.indiespot.mapped.MappedSet;
import net.indiespot.mapped.ann.MappedField;
import net.indiespot.mapped.impl.MappedObjectEnv;
public class MappedObjectDemo {
static {
MappedObjectEnv.BOUNDS_CHECKS = true;
}
public static void main(String[] args) throws Exception {
MappedObjectBuilder.fork(MappedObjectDemo.class, args);
demoVec3();
demoSet();
System.out.println("Done.");
}
@MappedType(stride=8)
public static class Vec2 extends MappedObjectArray {
public Vec2(ByteBuffer buffer) {
super(buffer);
}
@MappedField(offset = 0) public float x;
@MappedField(offset = 4) public float y;
}
public static class Vec3 extends MappedObjectArray {
public Vec3(ByteBuffer buffer) {
super(buffer);
}
@MappedField(offset = 0) public float x;
@MappedField(offset = 4) public float y;
@MappedField(offset = 8) public float z;
}
public static class VNC extends MappedSet {
public VNC(ByteBuffer buffer) {
super(buffer);
}
public Vec3 vertex;
public Vec3 normal;
public Vec2 texcoord;
}
public static void demoVec3() {
ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024);
bb.order(ByteOrder.nativeOrder());
Vec3 v3 = MappedObjectFactory.map(Vec3.class, bb);
// test 1
v3.x = 13.14f;
v3.y = 14.15f;
v3.z = 15.16f;
if (v3.x != 13.14f || bb.getFloat(0) != 13.14f) throw new IllegalStateException();
if (v3.y != 14.15f || bb.getFloat(4) != 14.15f) throw new IllegalStateException();
if (v3.z != 15.16f || bb.getFloat(8) != 15.16f) throw new IllegalStateException();
// move over data using a sliding window
v3.index(1337);
// test 2
v3.x = -13.14f;
v3.y = -14.15f;
v3.z = -15.16f;
if (v3.x != -13.14f || bb.getFloat(v3.stride() * 1337 + 0) != -13.14f) throw new IllegalStateException();
if (v3.y != -14.15f || bb.getFloat(v3.stride() * 1337 + 4) != -14.15f) throw new IllegalStateException();
if (v3.z != -15.16f || bb.getFloat(v3.stride() * 1337 + 8) != -15.16f) throw new IllegalStateException();
}
public static void demoSet(){
ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024);
bb.order(ByteOrder.nativeOrder());
VNC vnc = new VNC(bb);
vnc.index(1337);
if (vnc.vertex.index() != 1337) throw new IllegalStateException();
if (vnc.normal.index() != 1337) throw new IllegalStateException();
if (vnc.texcoord.index() != 1337) throw new IllegalStateException();
if(vnc.vertex.stride() != vnc.normal.stride()) throw new IllegalStateException();
if(vnc.vertex.stride() != vnc.texcoord.stride()) throw new IllegalStateException();
}
}
Javadoc:
[x] http://indiespot.net/files/projects/mappedobjectlib/mappedobject-0.8.5-doc/index.html
Classpath:
[x] http://indiespot.net/files/projects/mappedobjectlib/mappedobject-0.8.5.jar
[x] http://indiespot.net/files/projects/mappedobjectlib/asm-3.2.jar
[x] http://indiespot.net/files/projects/mappedobjectlib/asm-util-3.2.jar
Main Class:
[x] net.indiespot.mapped.demo.MappedObjectDemo