From 5230a575677d26d208e35f04131882130989499e Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 6 Oct 2022 15:00:49 +0200 Subject: [PATCH 1/3] improve performance when scanning for quests --- .../data/osm/osmquests/OsmQuestController.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt b/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt index 11efbf7510..3a988d5dbd 100644 --- a/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt +++ b/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt @@ -10,6 +10,7 @@ import de.westnordost.streetcomplete.data.osm.mapdata.Element import de.westnordost.streetcomplete.data.osm.mapdata.ElementKey import de.westnordost.streetcomplete.data.osm.mapdata.LatLon import de.westnordost.streetcomplete.data.osm.mapdata.MapDataWithGeometry +import de.westnordost.streetcomplete.data.osm.mapdata.MutableMapDataWithGeometry import de.westnordost.streetcomplete.data.osmnotes.Note import de.westnordost.streetcomplete.data.osmnotes.edits.NotesWithEditsSource import de.westnordost.streetcomplete.data.quest.OsmQuestKey @@ -145,6 +146,7 @@ class OsmQuestController internal constructor( val time = currentTimeMillis() val countryBoundaries = countryBoundariesFuture.get() + val elementsWithTags = MutableMapDataWithGeometry(mapDataWithGeometry.filter { it.tags.isNotEmpty() }, emptyList()) val deferredQuests: List>> = questTypes.map { questType -> scope.async { @@ -156,7 +158,11 @@ class OsmQuestController internal constructor( } else { val questTime = currentTimeMillis() var questCount = 0 - for (element in questType.getApplicableElements(mapDataWithGeometry)) { + val mapDataToUse = if (questType is OsmFilterQuestType) + elementsWithTags + else + mapDataWithGeometry + for (element in questType.getApplicableElements(mapDataToUse)) { val geometry = mapDataWithGeometry.getGeometry(element.type, element.id) ?: continue if (!mayCreateQuest(questType, geometry, bbox)) continue From 55137d287a6eb4a91933d2bf01684b582e10c352 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 6 Oct 2022 20:44:33 +0200 Subject: [PATCH 2/3] make sure onlyElementsWithTags is used only if it's safe --- .../data/osm/osmquests/OsmQuestController.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt b/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt index 3a988d5dbd..5177d38b37 100644 --- a/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt +++ b/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuestController.kt @@ -146,7 +146,12 @@ class OsmQuestController internal constructor( val time = currentTimeMillis() val countryBoundaries = countryBoundariesFuture.get() - val elementsWithTags = MutableMapDataWithGeometry(mapDataWithGeometry.filter { it.tags.isNotEmpty() }, emptyList()) + + // Remove elements without tags, to be used for quests that are never applicable without + // tags. These quests are usually OsmFilterQuestType, where questType.filter.mayEvaluateToTrueWithNoTags + // guarantees we can skip elements without tags completely. Also those quests don't use geometry. + // This shortcut reduces time for creating quests by ~15-30%. + val onlyElementsWithTags = MutableMapDataWithGeometry(mapDataWithGeometry.filter { it.tags.isNotEmpty() }, emptyList()) val deferredQuests: List>> = questTypes.map { questType -> scope.async { @@ -158,8 +163,8 @@ class OsmQuestController internal constructor( } else { val questTime = currentTimeMillis() var questCount = 0 - val mapDataToUse = if (questType is OsmFilterQuestType) - elementsWithTags + val mapDataToUse = if (questType is OsmFilterQuestType && !questType.filter.mayEvaluateToTrueWithNoTags) + onlyElementsWithTags else mapDataWithGeometry for (element in questType.getApplicableElements(mapDataToUse)) { From 70b6f67a2530d42bf3ab6c99f617003f091c0feb Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 6 Oct 2022 20:45:25 +0200 Subject: [PATCH 3/3] make mayEvaluateToTrueWithNoTags public --- .../data/elementfilter/ElementFilterExpression.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/de/westnordost/streetcomplete/data/elementfilter/ElementFilterExpression.kt b/app/src/main/java/de/westnordost/streetcomplete/data/elementfilter/ElementFilterExpression.kt index 77c14bfe33..12ee203d24 100644 --- a/app/src/main/java/de/westnordost/streetcomplete/data/elementfilter/ElementFilterExpression.kt +++ b/app/src/main/java/de/westnordost/streetcomplete/data/elementfilter/ElementFilterExpression.kt @@ -65,7 +65,7 @@ class ElementFilterExpression( internal val elementExprRoot: BooleanExpression? ) { /* Performance improvement: Allows to skip early on elements that have no tags at all */ - private val mayEvaluateToTrueWithNoTags = elementExprRoot?.mayEvaluateToTrueWithNoTags ?: true + val mayEvaluateToTrueWithNoTags = elementExprRoot?.mayEvaluateToTrueWithNoTags ?: true /** returns whether the given element is found through (=matches) this expression */ fun matches(element: Element): Boolean =