Итак, я пытаюсь провести тестирование, просматривая 3_000_000 точечных элементов и выполняя простую операцию сложения для каждой точки. Точное сравнение между этими точками, объявленными обычным способом Java в качестве класса Point, и созданием Point [] и использованием OpenHFT Chronicle-Values для создания уплощенной структуры памяти точек. Вот код:
public interface Point {
double getX();
void setX(double x);
double getY();
void setY(double y);
static int sizeOf() { return 16; }
}
public interface PointArray {
@Array(length=3_000_000)
Point getPointAt(int index);
void setPointAt(int index, Point point);
}
public class PointImplForComp {
public PointImplForComp(double x, double y) {
this.x = x;
this.y = y;
}
public double x;
public double y;
}
package benchmarks;
import net.openhft.chronicle.bytes.Byteable;
import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.values.Values;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import values.Point;
import values.PointArray;
import values.PointImplForComp;
public class Benchmarks {
@Benchmark
@Fork(value = 1, warmups = 5)
public static void sumPointsNative() {
PointArray pointArray = generateOffHeapValueArray();
double sum = 0;
for (int i = 0 ; i < 3_000_000; i++) {
sum = pointArray.getPointAt(i).getX() + pointArray.getPointAt(i).getY();
}
}
@Benchmark
@Fork(value = 1, warmups = 5)
public static void sumPointsVM() {
PointImplForComp[] pointImplForComps = generateVMPointArray();
double sum = 0;
for (int i = 0 ; i < 3_000_000; i++) {
sum = pointImplForComps[i].x + pointImplForComps[i].y;
}
}
private static PointArray generateOffHeapValueArray() {
final int nrOfElements = 3_000_000;
byte[] layoutContainer = new byte[nrOfElements * Point.sizeOf()];
PointArray offHeapPointArray = Values.newNativeReference(PointArray.class);
((Byteable) offHeapPointArray).bytesStore(BytesStore.wrap(layoutContainer), 0, layoutContainer.length);
for (int i = 0; i < nrOfElements; i++) {
offHeapPointArray.setPointAt(i, generatePointValue(i, i, layoutContainer, i * Point.sizeOf(), Point.sizeOf())); // each point has 16 bytes so the offset starts from 0_16; 16_32 (1 * 16_1* 16 + 16)
}
return offHeapPointArray;
}
// use the array layout
private static Point generatePointValue(long x, long y, byte[] layoutContainer, int offset, int length) {
Point offHeapPoint = Values.newNativeReference(Point.class);
((Byteable) offHeapPoint).bytesStore(BytesStore.wrap(layoutContainer), offset, length);
offHeapPoint.setX(x);
offHeapPoint.setY(y);
return offHeapPoint;
}
private static PointImplForComp[] generateVMPointArray() {
final int nrOfElements = 3_000_000;
PointImplForComp[] points = new PointImplForComp[nrOfElements];
for (int i = 0; i < nrOfElements; i++) {
points[i] = new PointImplForComp(i, i);
}
return points;
}
}
Результаты показывают, что я получаю на 30_000 больше операций в секунду от функции sumPointsVM (), что оказалось не таким, как я ожидал, по меньшей мере. Я уверен, что не правильно использую значения хроники, но кто-то может дать мне кивок в правильном направлении? Примеры скудны и API не интуитивно понятен. Я даже не знаю, почему я не могу найти метод для освобождения созданной собственной памяти или это действительно собственная память, потому что я использую экземпляр Values.newNAtiveReference, но также использую вспомогательный байт [], а не адрес памяти вне кучи.