From 884a4326768e6207aca2b1a4a470d4618ed3c76f Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 1 May 2024 11:59:04 +0700 Subject: [PATCH] Make EntityIndex#walk significantly faster when querying large regions --- .../kstarbound/world/EntityIndex.kt | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/EntityIndex.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/EntityIndex.kt index 16bcb4d0..a002bc1e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/EntityIndex.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/EntityIndex.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.kstarbound.world import it.unimi.dsi.fastutil.ints.IntAVLTreeSet +import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.Long2ObjectFunction import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongArrayList @@ -317,7 +318,7 @@ class EntityIndex(val geometry: WorldGeometry) { } fun walk(rect: AABB, visitor: (AbstractEntity) -> KOptional, withEdges: Boolean = true): KOptional { - val seen = IntAVLTreeSet() + val seen = IntOpenHashSet(256) for (actualRegion in geometry.split(rect).first) { val xMin = geometry.x.chunkFromCell(actualRegion.mins.x) @@ -327,15 +328,29 @@ class EntityIndex(val geometry: WorldGeometry) { val yMax = geometry.y.chunkFromCell(actualRegion.maxs.y) for (x in xMin .. xMax) { + val xIsEdge = x == xMin || x == xMax + for (y in yMin .. yMax) { val sector = map[index(x, y)] ?: continue + val yIsEdge = y == yMin || y == yMax - for (entry in sector.entries) { - if (seen.add(entry.id) && entry.intersects(actualRegion, withEdges)) { - val visit = visitor(entry.value) + if (!xIsEdge && !yIsEdge) { + for (entry in sector.entries) { + if (seen.add(entry.id)) { + val visit = visitor(entry.value) - if (visit.isPresent) - return visit + if (visit.isPresent) + return visit + } + } + } else { + for (entry in sector.entries) { + if (seen.add(entry.id) && entry.intersects(actualRegion, withEdges)) { + val visit = visitor(entry.value) + + if (visit.isPresent) + return visit + } } } }