From 59e0d6406e9c4ed769827871ee9b6192bcee8205 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Wed, 30 Jan 2019 20:19:54 -0800 Subject: [PATCH] premature optimization --- .../calc/openset/BinaryHeapOpenSet.java | 37 +++++++----- .../pathing/calc/openset/OpenSetsTest.java | 56 ++++++++++++++++--- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java index 33f077b9d..510fd23e3 100644 --- a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java +++ b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java @@ -72,6 +72,7 @@ public final class BinaryHeapOpenSet implements IOpenSet { int index = val.heapPosition; int parentInd = index >>> 1; double cost = val.combinedCost; + PathNode[] array = this.array; PathNode parentNode = array[parentInd]; while (index > 1 && parentNode.combinedCost > cost) { array[index] = parentNode; @@ -94,40 +95,50 @@ public final class BinaryHeapOpenSet implements IOpenSet { if (size == 0) { throw new IllegalStateException(); } + PathNode[] array = this.array; PathNode result = array[1]; PathNode val = array[size]; array[1] = val; val.heapPosition = 1; array[size] = null; - size--; + int size = --this.size; result.heapPosition = -1; if (size < 2) { return result; } int index = 1; - int smallerChild = 2; + int smallerChild = 1; double cost = val.combinedCost; - do { + while ((smallerChild <<= 1) < size) { PathNode smallerChildNode = array[smallerChild]; + PathNode otherChildNode = array[smallerChild + 1]; double smallerChildCost = smallerChildNode.combinedCost; - if (smallerChild < size) { - PathNode rightChildNode = array[smallerChild + 1]; - double rightChildCost = rightChildNode.combinedCost; - if (smallerChildCost > rightChildCost) { - smallerChild++; - smallerChildCost = rightChildCost; - smallerChildNode = rightChildNode; - } + double rightChildCost = otherChildNode.combinedCost; + if (smallerChildCost > rightChildCost) { + smallerChild++; + smallerChildCost = rightChildCost; + smallerChildNode = otherChildNode; } if (cost <= smallerChildCost) { - break; + return result; } array[index] = smallerChildNode; array[smallerChild] = val; val.heapPosition = smallerChild; smallerChildNode.heapPosition = index; index = smallerChild; - } while ((smallerChild <<= 1) <= size); + } + // if we get here, then smallerChild >= size + // one last swap to check + if (smallerChild == size) { + PathNode onlyChildNode = array[smallerChild]; + if (cost > onlyChildNode.combinedCost) { + array[index] = onlyChildNode; + array[smallerChild] = val; + val.heapPosition = smallerChild; + onlyChildNode.heapPosition = index; + } + } return result; } } diff --git a/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java b/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java index a12e0b7ae..bb415740c 100644 --- a/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java +++ b/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java @@ -36,24 +36,39 @@ public class OpenSetsTest { this.size = size; } + private static final ArrayList insertions = new ArrayList<>(); + private static final ArrayList removal1 = new ArrayList<>(); + private static final ArrayList removal2 = new ArrayList<>(); + @Parameterized.Parameters public static Collection data() { ArrayList testSizes = new ArrayList<>(); - for (int size = 1; size < 20; size++) { + /*for (int size = 1; size < 20; size++) { testSizes.add(new Object[]{size}); } for (int size = 100; size <= 1000; size += 100) { testSizes.add(new Object[]{size}); } testSizes.add(new Object[]{5000}); - testSizes.add(new Object[]{10000}); + testSizes.add(new Object[]{10000});*/ + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); + testSizes.add(new Object[]{100000}); return testSizes; } private static void removeAndTest(int amount, IOpenSet[] test, Optional> mustContain) { double[][] results = new double[test.length][amount]; for (int i = 0; i < test.length; i++) { - long before = System.nanoTime() / 1000000L; + long before = System.nanoTime(); for (int j = 0; j < amount; j++) { PathNode pn = test[i].removeLowest(); if (mustContain.isPresent() && !mustContain.get().contains(pn)) { @@ -61,7 +76,13 @@ public class OpenSetsTest { } results[i][j] = pn.combinedCost; } - System.out.println(test[i].getClass() + " " + (System.nanoTime() / 1000000L - before)); + long time = System.nanoTime() - before; + System.out.println(test[i].getClass() + " " + (time)); + if (mustContain.isPresent()) { + removal1.add(time); + } else { + removal2.add(time); + } } for (int j = 0; j < amount; j++) { for (int i = 1; i < test.length; i++) { @@ -75,10 +96,16 @@ public class OpenSetsTest { @Test public void testSize() { + try { + System.gc(); + Thread.sleep(1000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } System.out.println("Testing size " + size); // Include LinkedListOpenSet even though it's not performant because I absolutely trust that it behaves properly // I'm really testing the heap implementations against it as the ground truth - IOpenSet[] test = new IOpenSet[]{new BinaryHeapOpenSet(), new LinkedListOpenSet()}; + IOpenSet[] test = new IOpenSet[]{new BinaryHeapOpenSet()/*, new LinkedListOpenSet()*/}; for (IOpenSet set : test) { assertTrue(set.isEmpty()); } @@ -116,10 +143,12 @@ public class OpenSetsTest { System.out.println("Insertion"); for (IOpenSet set : test) { - long before = System.nanoTime() / 1000000L; + long before = System.nanoTime(); for (int i = 0; i < size; i++) set.insert(toInsert[i]); - System.out.println(set.getClass() + " " + (System.nanoTime() / 1000000L - before)); + long time = System.nanoTime() - before; + System.out.println(set.getClass() + " " + (time)); + insertions.add(time); //all three take either 0 or 1ms to insert up to 10,000 nodes //linkedlist takes 0ms most often (because there's no array resizing or allocation there, just pointer shuffling) } @@ -166,5 +195,18 @@ public class OpenSetsTest { for (IOpenSet set : test) { assertTrue(set.isEmpty()); } + + + printo(insertions); + printo(removal1); + printo(removal2); + + } + + private static void printo(ArrayList data) { + if (data.size() < 3) { + return; + } + System.out.println(data.subList(2, data.size()).stream().mapToLong(x -> x).average().getAsDouble() / 1000000D); } }