-
-
Notifications
You must be signed in to change notification settings - Fork 366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spatial cache for OsmQuestController, OsmNoteQuestController and MapDataController #4125
Conversation
Reading vertically through the code:
|
So:
|
Hmm right. I guess there are two options:
For the former case, the code in the controller would look like this: fun get(bbox) {
val tilesRect = bbox.asTileRect(zoom=16)
val data = cache.get(tilesRect)
return data.filter { it in bbox }
} This means that the cache first returns all the data from all the tiles that intersect the bbox, the controller filters it out afterwards. I reckon this may be a little unperformant, especially if the bboxes queried do not align with the tiles (thinking about map data cache here). For the latter, the code above would basically be in the cache. Though, it can already not add the element within each cached tile to the result set and have some additional logic that would not even check for each element if it is inside the bbox or not for tiles that are completely contained within the bbox. Hence, even faster. So overall, it looks like your original solution to which to use on the interface (bbox or tiles) is more performant. Plus, thinking about that there is the same cache class for all the controllers that manage geospatial data (quests, map data, notes), it is certainly less code because the above logic would not have to be repeated in each controller. |
The cache could return a A problem I see with a generic cache with lambdas is that the cache for
Actually I'm not sure how much really can be done here in a generic way, the logic for combining and filtering data will still need to be in the controller, either in |
IMO that's preliminary optimization. The controller can just
I don't understand, why would the combining (of the data in possibly several tiles) and filtering (the elements whether they are contained in the bbox) need to be done in the controller for the latter case, i.e. the |
I actually went from caching all quests to caching only visible quests because it makes a considerable difference when fetching from DB. A |
I don't understand why though. I guess it must be about the extra quests returned that are not visible. Are you sure that you create a Also, if this is still slow, there there is another solution than moving the cache to
|
That's what I concluded. The slow part is
Right, I didn't think of simply moving this from cache to the controller. |
Some semi-related comments: StreetComplete/app/src/main/java/de/westnordost/streetcomplete/util/math/SphericalEarthMath.kt Line 468 in c20190b
to operator fun BoundingBox.contains(pos: LatLon): Boolean {
StreetComplete/app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/OsmQuest.kt Line 20 in c20190b
And if yes, would it make sense to reduce calls e.g. by making OsmQuest.key by lazy?
I general I find measuring performance easy enough, but for things that may or may not waste memory I have
Is there some way Android Studio can help on the last point? |
I did some comparison between the current cache(s) for There is some difference in memory usage, judging by java memory part of the Android Studio memory profiler. Loading 8 tiles into cache increases java from ~26 to 32 for one cache, while for the cache in this PR it goes up to 44. |
yes
only if it is the same override val key = OsmQuestKey(elementType, elementId, questTypeName)
Yes, it's quite powerful, too: https://developer.android.com/studio/profile/memory-profiler |
Currently the
Ok, thanks! |
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/data/osm/osmquests/SpatialCache.kt
Outdated
Show resolved
Hide resolved
Probably. I am not sure how quickly the garbage collector will collect it. IIRC there is a call you can make to force garbage collecting now (IMO useful only for debugging). |
I've now reviewed the SpatialClass class only so far. Looks quite good already, I only found one conceptual issue. I will review the rest later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I re-read the things you clarified in code and added some comments etc myself, see the git change history
app/src/main/java/de/westnordost/streetcomplete/data/osm/mapdata/MapDataCache.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/de/westnordost/streetcomplete/util/SpatialCache.kt
Outdated
Show resolved
Hide resolved
(Please also note the TODOs I added in the code, requesting you to write an explanatory comment why it is done like that, in case you missed them) |
Thanks for adding the explanatory comments! |
fix conversion of tiles from/to bboxes (#4125)
So, this is done except responding to my remark regarding caching |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, ready to merge, right? I suppose even if you planned to add some more tests for MapDataCache, it might as well be a separate PR
Yes, it's ready. |
I skimmed through the implementation and compared to the tests that exist so far. Note that the implementation is different for ways and relations, thus putting ways and relations into one bucket in the tests mean that one of the two execution paths are not covered Striked points are what I already found in the tests (updated Sept 29, 14:02): Missing tests
Current tests
|
I updated/clarified and added a few of the tests... |
Very cool! I updated the above list |
now done: ways by node id does return just replaced way that now does contain the node but before it didnt relations by member does return just replaced relation that now does contain the node but before it didnt ways by node id does not return just deleted way relations by member does not return just deleted relation get multiple elements, all are cached get multiple elements, some are cached get multiple elements, none are cached get multiple nodes, all are cached get multiple nodes, some are cached get multiple nodes, none are cached get multiple geometries, all are cached get multiple geometries, some are cached get multiple geometries, none are cached |
Awesome! |
Added some more tests covering the "is in spatial cache" logic And a test each for
The rest will come later with a PR... |
Perfect! Man, this PR is so massive, both in effort invested and in the gain provided! I'm glad that it can go live finally in v48 :-) |
It's also by far the most commented/reviewed one, and, the 1000ths closed pull request 🥳 |
A first version for the
OsmQuestController
cache discussed in #4079.I left the comments to clarify my motivations.
Main benefits
get
for quests in view (called on opening and solving quests)getAllVisibleInBBox
when tiles are cached, otherwise marginally slowerThis translates to a ~30% improvement of
QuestPinsManager.onNewTilesRect
, as creating and updating pins is rather slow.What is missing: