-
Notifications
You must be signed in to change notification settings - Fork 319
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
Shields loading optimization #6826
base: main
Are you sure you want to change the base?
Shields loading optimization #6826
Conversation
- deleted duplicate image cache - ShieldsCache and ShieldByteArrayCache were caching same data twice - separated download from caching logic by introducing ResourceLoader and CacheResourceLoader local interfaces - renamed ShieldResultCache -> RoadShieldLoader and loosely coupled it with sprites and image loaders - updated RoadShieldContentManagerImpl - loosely coupled it with loader class
ChangelogFeatures
Bug fixes and improvements
Known issues
|
|
||
private typealias LoaderCallback<R> = (Expected<String, R>) -> Unit | ||
|
||
internal abstract class ResourceDownloader<I, R> : ResourceLoader<I, R> { |
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" stands for "input"?
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.
Yes
|
||
import com.mapbox.bindgen.Expected | ||
|
||
internal fun interface ResourceLoader<Argument, Resource> { |
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.
There is already a ResourceLoader
in com.mapbox.navigation.ui.utils.internal.resource
. Can we reuse that one? I find 2 classes with the same quite an abstract name confusing.
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.
No. They are not the same. The utils ResourceLoader
is a global facade over the native TileStore, and it acts more like Downloader than a local loader (maybe ResourceDownloader
would be a better name for it).
This ResourceLoader
is an internal interface. It offers an abstraction for a generic, async loader and helps break tight coupling between the RoadShieldContentManager
and concrete loaders.
I am aware that the name clashes with the utils version. We can shorten it to just a Loader
if it helps. Furthermore, I would like to introduce this abstraction here first and later, if we find it useful elsewhere, move it to the utils module as well.
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.
They should have different names. Especially considering the fact they are interfaces. So you can't even just look at the class code and understand the difference.
Maybe the utils one should be TileStoreResourcesLoader
or sth like that. Since it uses Common classes in the API anyway.
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.
Since they are internal interfaces they don't have to have different names.
Anyway, I've renamed it to just Loader
.
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.
Since they are internal interfaces they don't have to have different names.
Technically of course they don't, but for better understanding they should. Especially considering the fact that utils ResourceLoader is accessible from other modules.
Anyway, I've renamed it to just Loader.
It's not really helpful. Now it looks like the ResourceLoader should implement Loader and Loader should be in utils module as well since it's general enough. I think in this case specifying what utils ResourceLoader
does is a better way. TileStoreResourceLoader
, for example.
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.
No
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.
What exactly are you negating here? And why?
What don't you like about my suggestion and what are the advantages of yours?
|
||
private typealias LoaderCallback<R> = (Expected<String, R>) -> Unit | ||
|
||
internal abstract class ResourceDownloader<I, R> : ResourceLoader<I, R> { |
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.
Why don't you use TileStore
cache? Aren't your needs met by TileStore
?
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.
RoadShieldDownloader
implicitly uses TIleStore
via the utils ResourceLoader
facade.
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.
Yes, but isn't the cache TileStore
provides enough? I can assume it's not because it was not enough for voice instructions. Just want to make sure that writing our own cache above TileStore
is a conscious choice.
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.
Just want to make sure that writing our own cache above TileStore is a conscious choice.
What's that supposed to mean? First, of course, it is a conscious choice! Second, loading voice instructions don't require parsing large JSON strings with ~400 entries. Third, shields require loading two resources: a) a sprites list; b) images. Finally, the in-memory cache is necessary to avoid redundant I/O requests and computationally heavy result processing.
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.
It means that we are aware that TileStore
provides us with a caching mechanism but we write our own because it doesn't meet our needs.
…pdated return type to return Expected<Error, V> instead of Expected<String, V>
Codecov Report
@@ Coverage Diff @@
## main #6826 +/- ##
============================================
- Coverage 72.64% 72.61% -0.04%
- Complexity 5569 5600 +31
============================================
Files 780 783 +3
Lines 30104 30106 +2
Branches 3553 3555 +2
============================================
- Hits 21869 21860 -9
- Misses 6808 6815 +7
- Partials 1427 1431 +4
|
@abhishek1508 Can you review and merge this? |
cc @LukasPaczos |
Closes NAVAND-483
Description
After reviewing RoadShiled loading logic, I've noticed that we were caching RoadShield image data in 3 different places.
ShieldResultCache
-RouteShield
in LruCacheShieldByteArrayCache
-ByteArray
in LruCacheTileStore
-ByteArray
on diskThe
ShieldResultCache
already caches image data together withRouteShield
; therefore,ShieldByteArrayCache
is redundant.In this PR, I optimized RoadShield loading by:
ShieldResultCache
->RoadShieldLoader
and loosely coupling it with sprites and image loadersRoadShieldContentManagerImpl
with theRoadShieldLoader
class(new setup)