From fe4f33f070556c32c317421893184b8c16a74fe4 Mon Sep 17 00:00:00 2001 From: Bryson Zimmerman Date: Wed, 20 Nov 2024 11:34:46 -0500 Subject: [PATCH] Add benchmarking functionality --- src/main/kotlin/ArrayBackedPathfinder.kt | 7 +-- src/main/kotlin/Main.kt | 60 ++++++++++++++++-------- src/main/kotlin/MapBackedPathfinder.kt | 4 +- src/main/kotlin/MazeFinder.kt | 3 +- src/main/kotlin/World.kt | 11 ++++- 5 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/ArrayBackedPathfinder.kt b/src/main/kotlin/ArrayBackedPathfinder.kt index 4745c7a..487876c 100644 --- a/src/main/kotlin/ArrayBackedPathfinder.kt +++ b/src/main/kotlin/ArrayBackedPathfinder.kt @@ -4,6 +4,7 @@ import technology.zim.data.Directions import technology.zim.data.Tile import technology.zim.data.TileHeap import technology.zim.data.TileNavigatedArray +import kotlin.Int import kotlin.math.abs //A* pathfinder backed by an array to improve efficiency @@ -12,7 +13,7 @@ import kotlin.math.abs //and https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Comparator.html object ArrayBackedPathfinder { - val gVals = TileNavigatedArray(World.sizeX, World.sizeY, false) + var gVals = TileNavigatedArray(World.sizeX, World.sizeY, false) //work along the path, marking tiles with VISITED along the way //if marking with visited is too expensive, just make the path and finalize it fun generatePath(start: Tile, end: Tile) { @@ -25,7 +26,7 @@ object ArrayBackedPathfinder { println("Ouroboros detected") return } - + gVals = TileNavigatedArray(World.sizeX, World.sizeY, false) val frontier = TileHeap(end, this::fValue) //Prime the things @@ -55,7 +56,7 @@ object ArrayBackedPathfinder { //At this point, a path is found markPath(start, end) - println("Path found!") + //println("Path found!") } fun markPath(start: Tile, end:Tile) { diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 805e7e7..5d843b4 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -1,6 +1,7 @@ package technology.zim import technology.zim.data.Tile +import java.io.File import java.text.NumberFormat import java.util.Locale import kotlin.time.measureTime @@ -20,41 +21,60 @@ class HierarchicalPathfinding { companion object { @JvmStatic fun main(args: Array) { - val n = 1000 - println("Building maze") - val buildMazeTime = measureTime { - buildMaze(n) + val benchmarking = false + val ns = arrayListOf(50, 100, 250, 500, 750, 1000) + val iterations = 10 + val file = File("performance.csv") + file.writeText("n, build, bfs, astar-array, astar-hashmap\n") + + if(benchmarking) { + for (n in ns) { + for (i in 0 until iterations) { + doTheThing(n, file) + } + } } + else + doTheThing(500, file) + /* + val numberFormat = NumberFormat.getInstance(Locale.US) + println(World.toString()) + println(numberFormat.format(n*n)) + println("Maze build time: ${numberFormat.format(buildMazeTime.inWholeMilliseconds)} ms") + println("BFS Pathfinder time: ${numberFormat.format(bfsPathfinderTime.inWholeMilliseconds)}ms") + println("Array-Backed Pathfinder time: ${numberFormat.format(arrayBackedPathfinderTime.inWholeMilliseconds)}ms") + println("HashMap-Backed Pathfinder time: ${numberFormat.format(mapBackedPathfinderTime.inWholeMilliseconds)}ms") + */ + } - println("Pathfinding") + fun doTheThing(n:Int, file:File) { + World.clear() - val bfsPathfinderTime = measureTime { - BFSPathfinder.generatePath(Tile(0, 0), Tile(n-1, n-1)) + var buildMazeTime = measureTime { + buildMaze(n) + } + + var bfsPathfinderTime = measureTime { + BFSPathfinder.generatePath(Tile(0, 0), Tile(n - 1, n - 1)) } - val arrayBackedPathfinderTime = measureTime { - ArrayBackedPathfinder.generatePath(Tile(0, 0), Tile(n - 1, (n - 1))) + var arrayBackedPathfinderTime = measureTime { + ArrayBackedPathfinder.generatePath(Tile(0, 0), Tile(n - 1, n - 1)) } - val mapBackedPathfinderTime = measureTime { - MapBackedPathfinder.generatePath(Tile(0, 0), Tile(n - 1, (n - 1))) + var mapBackedPathfinderTime = measureTime { + MapBackedPathfinder.generatePath(Tile(0, 0), Tile(n - 1, n - 1)) } + file.appendText("${n},${buildMazeTime.inWholeMilliseconds},${bfsPathfinderTime.inWholeMilliseconds},${arrayBackedPathfinderTime.inWholeMilliseconds},${mapBackedPathfinderTime.inWholeMilliseconds}\n") - val numberFormat = NumberFormat.getInstance(Locale.US) - println(World.toString()) - println(numberFormat.format(n*n)) - println("Maze build time: ${numberFormat.format(buildMazeTime.inWholeMilliseconds)} ms") - println("BFS Pathfinder time: ${numberFormat.format(bfsPathfinderTime.inWholeMilliseconds)}ms") - println("Array-Backed Pathfinder time: ${numberFormat.format(arrayBackedPathfinderTime.inWholeMilliseconds)}ms") - println("HashMap-Backed Pathfinder time: ${numberFormat.format(mapBackedPathfinderTime.inWholeMilliseconds)}ms") } fun buildMaze(n: Int) { - println("Building world") + //println("Building world") World.setSize(n, n) - println("Start") + //println("Start") try { MazeFinder.primsAlgorithm() diff --git a/src/main/kotlin/MapBackedPathfinder.kt b/src/main/kotlin/MapBackedPathfinder.kt index a596d71..5d748f3 100644 --- a/src/main/kotlin/MapBackedPathfinder.kt +++ b/src/main/kotlin/MapBackedPathfinder.kt @@ -23,7 +23,7 @@ object MapBackedPathfinder { println("Ouroboros detected") return } - + gVals.clear() val frontier = TileHeap(end, this::fValue) //Prime the things @@ -52,7 +52,7 @@ object MapBackedPathfinder { } while( current != end) //At this point, a path is found - println("Path found!") + //println("Path found!") markPath(start, end) } diff --git a/src/main/kotlin/MazeFinder.kt b/src/main/kotlin/MazeFinder.kt index f8984d2..d806264 100644 --- a/src/main/kotlin/MazeFinder.kt +++ b/src/main/kotlin/MazeFinder.kt @@ -26,6 +26,7 @@ object MazeFinder { } fun primsAlgorithm() { + frontier.clear() //Prime the graph with the first connection, which marks the first visited Tiles val startingTile = World.getRandomLocation() val connectorTile = startingTile.getAdjacentTiles(false).random() @@ -62,7 +63,7 @@ object MazeFinder { //println("--------------------------------------------") } - println("prim") + //println("prim") } private fun addToManifest(current: Tile) { diff --git a/src/main/kotlin/World.kt b/src/main/kotlin/World.kt index c06b717..b87ccbd 100644 --- a/src/main/kotlin/World.kt +++ b/src/main/kotlin/World.kt @@ -20,7 +20,7 @@ import technology.zim.data.TileNavigatedArray @Suppress("unused") object World { //Default size should be 10 - val tiles = TileNavigatedArray() + var tiles = TileNavigatedArray() var sizeX = 10 //Default size var sizeY = 10 const val ANSI_RESET = "\u001B[0m" @@ -54,6 +54,15 @@ object World { sizeX = x sizeY = y tiles.resize(x, y) + tiles.forEachIndexed { + i, t -> + tiles.set(i, TileProperties(0)) + } + } + + fun clear() { + tiles = TileNavigatedArray() + setSize(sizeX, sizeY) } override fun toString(): String {