package com.github.davidmoten.rtree; import static com.github.davidmoten.rtree.Utilities.entries1000; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; import com.github.davidmoten.rtree.fbs.SerializerFlatBuffers; import com.github.davidmoten.rtree.geometry.Geometries; import com.github.davidmoten.rtree.geometry.Point; import com.github.davidmoten.rtree.geometry.Rectangle; import rx.Subscriber; import rx.functions.Func1; @State(Scope.Benchmark) public class BenchmarksRTree { private final List<Entry<Object, Point>> entries = GreekEarthquakes.entriesList(); private final List<Entry<Object, Rectangle>> some = entries1000(); private final RTree<Object, Point> defaultTreeM4 = RTree.maxChildren(4).<Object, Point> create() .add(entries); private final RTree<Object, Point> defaultTreeM10 = RTree.maxChildren(10) .<Object, Point> create().add(entries); private final RTree<Object, Point> starTreeM4 = RTree.maxChildren(4).star() .<Object, Point> create().add(entries); private final RTree<Object, Point> starTreeM10 = RTree.maxChildren(10).star() .<Object, Point> create().add(entries); private final RTree<Object, Point> defaultTreeM32 = RTree.maxChildren(32) .<Object, Point> create().add(entries); private final RTree<Object, Point> starTreeM32 = RTree.maxChildren(32).star() .<Object, Point> create().add(entries); private final RTree<Object, Point> defaultTreeM128 = RTree.maxChildren(128) .<Object, Point> create().add(entries); private final RTree<Object, Point> starTreeM128 = RTree.maxChildren(128).star() .<Object, Point> create().add(entries); private final RTree<Object, Rectangle> smallDefaultTreeM4 = RTree.maxChildren(4) .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallDefaultTreeM10 = RTree.maxChildren(10) .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallStarTreeM4 = RTree.maxChildren(4).star() .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallStarTreeM10 = RTree.maxChildren(10).star() .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallDefaultTreeM32 = RTree.maxChildren(32) .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallStarTreeM32 = RTree.maxChildren(32).star() .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallDefaultTreeM128 = RTree.maxChildren(128) .<Object, Rectangle> create().add(some); private final RTree<Object, Rectangle> smallStarTreeM128 = RTree.maxChildren(128).star() .<Object, Rectangle> create().add(some); private final byte[] byteArrayGreek = createFlatBuffersByteArrayGreek(); private final RTree<Object, Point> starTreeM10FlatBuffers = createFlatBuffersGreek(); @Benchmark public void defaultRTreeInsertOneEntryIntoGreekDataEntriesMaxChildren004() { insertPoint(defaultTreeM4); } private byte[] createFlatBuffersByteArrayGreek() { RTree<Object, Point> tree = RTree.maxChildren(10).star().<Object, Point> create() .add(entries); final ByteArrayOutputStream os = new ByteArrayOutputStream(); Func1<Object, byte[]> serializer = new Func1<Object, byte[]>() { @Override public byte[] call(Object o) { return new byte[0]; } }; Func1<byte[], Object> deserializer = new Func1<byte[], Object>() { @Override public Object call(byte[] bytes) { return null; } }; Serializer<Object, Point> fbSerializer = SerializerFlatBuffers.create(serializer, deserializer); try { fbSerializer.write(tree, os); os.close(); return os.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } } private RTree<Object, Point> createFlatBuffersGreek() { Func1<Object, byte[]> serializer = new Func1<Object, byte[]>() { @Override public byte[] call(Object o) { return new byte[0]; } }; Func1<byte[], Object> deserializer = new Func1<byte[], Object>() { @Override public Object call(byte[] bytes) { return null; } }; Serializer<Object, Point> fbSerializer = SerializerFlatBuffers.create(serializer, deserializer); try { ByteArrayInputStream is = new ByteArrayInputStream(byteArrayGreek); return fbSerializer.read(is, byteArrayGreek.length, InternalStructure.SINGLE_ARRAY); } catch (IOException e) { throw new RuntimeException(e); } } @Benchmark public void defaultRTreeCreation010() { RTree.maxChildren(10).<Object, Point> create().add(entries); } @Benchmark public void starRTreeCreation010() { RTree.maxChildren(10).star().<Object, Point> create().add(entries); } @Benchmark public void flatBufferRTreeCreation010() { createFlatBuffersGreek(); } @Benchmark public void bulkLoadingRTreeCreation010() { RTree.maxChildren(10).<Object, Point> create(entries); } @Benchmark public void bulkLoadingFullRTreeCreation010() { RTree.maxChildren(10).loadingFactor(1.0).<Object, Point> create(entries); } @Benchmark public void defaultRTreeSearchOfGreekDataPointsMaxChildren004() { searchGreek(defaultTreeM4); } @Benchmark public void defaultRTreeInsertOneEntryIntoGreekDataEntriesMaxChildren010() { insertPoint(defaultTreeM10); } @Benchmark public void defaultRTreeSearchOfGreekDataPointsMaxChildren010() { searchGreek(defaultTreeM10); } @Benchmark public void rStarTreeInsertOneEntryIntoGreekDataEntriesMaxChildren004() { insertPoint(starTreeM4); } @Benchmark public void rStarTreeInsertOneEntryIntoGreekDataEntriesMaxChildren010() { insertPoint(starTreeM10); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren004() { searchGreek(starTreeM4); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren010() { searchGreek(starTreeM10); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren010FlatBuffers() { searchGreek(starTreeM10FlatBuffers); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren010FlatBuffersBackpressure() { searchGreekBackpressure(starTreeM10FlatBuffers); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren010WithBackpressure() { searchGreekWithBackpressure(starTreeM10); } @Benchmark public void defaultRTreeInsertOneEntryIntoGreekDataEntriesMaxChildren032() { insertPoint(defaultTreeM32); } @Benchmark public void defaultRTreeSearchOfGreekDataPointsMaxChildren032() { searchGreek(defaultTreeM32); } @Benchmark public void rStarTreeInsertOneEntryIntoGreekDataEntriesMaxChildren032() { insertPoint(starTreeM32); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren032() { searchGreek(starTreeM32); } @Benchmark public void defaultRTreeInsertOneEntryIntoGreekDataEntriesMaxChildren128() { insertPoint(defaultTreeM128); } @Benchmark public void defaultRTreeSearchOfGreekDataPointsMaxChildren128() { searchGreek(defaultTreeM128); } @Benchmark public void rStarTreeInsertOneEntryIntoGreekDataEntriesMaxChildren128() { insertPoint(starTreeM128); } @Benchmark public void rStarTreeSearchOfGreekDataPointsMaxChildren128() { searchGreek(starTreeM128); } @Benchmark public void defaultRTreeInsertOneEntryInto1000EntriesMaxChildren004() { insertRectangle(smallDefaultTreeM4); } @Benchmark public void defaultRTreeSearchOf1000PointsMaxChildren004() { search(smallDefaultTreeM4); } @Benchmark public void defaultRTreeInsertOneEntryInto1000EntriesMaxChildren010() { insertRectangle(smallDefaultTreeM10); } @Benchmark public void defaultRTreeSearchOf1000PointsMaxChildren010() { search(smallDefaultTreeM10); } @Benchmark public void rStarTreeInsertOneEntryInto1000EntriesMaxChildren004() { insertRectangle(smallStarTreeM4); } @Benchmark public void rStarTreeInsertOneEntryInto1000EntriesMaxChildren010() { insertRectangle(smallStarTreeM10); } @Benchmark public void rStarTreeSearchOf1000PointsMaxChildren004() { search(smallStarTreeM4); } @Benchmark public void rStarTreeSearchOf1000PointsMaxChildren010() { search(smallStarTreeM10); } @Benchmark public void defaultRTreeInsertOneEntryInto1000EntriesMaxChildren032() { insertRectangle(smallDefaultTreeM32); } @Benchmark public void defaultRTreeSearchOf1000PointsMaxChildren032() { search(smallDefaultTreeM32); } @Benchmark public void rStarTreeInsertOneEntryInto1000EntriesMaxChildren032() { insertRectangle(smallStarTreeM32); } @Benchmark public void rStarTreeSearchOf1000PointsMaxChildren032() { search(smallStarTreeM32); } @Benchmark public void defaultRTreeInsertOneEntryInto1000EntriesMaxChildren128() { insertRectangle(smallDefaultTreeM128); } @Benchmark public void defaultRTreeSearchOf1000PointsMaxChildren128() { search(smallDefaultTreeM128); } @Benchmark public void rStarTreeInsertOneEntryInto1000EntriesMaxChildren128() { insertRectangle(smallStarTreeM128); } @Benchmark public void rStarTreeSearchOf1000PointsMaxChildren128() { search(smallStarTreeM128); } @Benchmark public void rStarTreeDeleteOneEveryOccurrenceFromGreekDataChildren010() { deleteAll(starTreeM10); } @Benchmark public void searchNearestGreek() { searchNearestGreek(starTreeM4); } private void deleteAll(RTree<Object, Point> tree) { tree.delete(entries.get(1000), true); } private void search(RTree<Object, Rectangle> tree) { // returns 10 results tree.search(Geometries.rectangle(500, 500, 630, 630)).subscribe(); } private void searchGreek(RTree<Object, Point> tree) { // should return 22 results tree.search(Geometries.rectangle(40, 27.0, 40.5, 27.5)).subscribe(); } private void searchGreekBackpressure(RTree<Object, Point> tree) { // should return 22 results tree.search(Geometries.rectangle(40, 27.0, 40.5, 27.5)).take(1000).subscribe(); } private void searchNearestGreek(RTree<Object, Point> tree) { tree.nearest(Geometries.point(40.0, 27.0), 1, 300).subscribe(); } private void searchGreekWithBackpressure(RTree<Object, Point> tree) { // should return 22 results tree.search(Geometries.rectangle(40, 27.0, 40.5, 27.5)).subscribe(new Subscriber<Object>() { @Override public void onStart() { request(1); } @Override public void onCompleted() { } @Override public void onError(Throwable arg0) { } @Override public void onNext(Object arg0) { request(1); } }); } private void insertRectangle(RTree<Object, Rectangle> tree) { tree.add(new Object(), RTreeTest.random()); } private void insertPoint(RTree<Object, Point> tree) { tree.add(new Object(), Geometries.point(Math.random() * 1000, Math.random() * 1000)); } public static void main(String[] args) { BenchmarksRTree b = new BenchmarksRTree(); System.out.println("starting searches"); while (true) b.rStarTreeSearchOfGreekDataPointsMaxChildren010FlatBuffers(); } }