mapbox / mapbox-sdk-cs

C# libraries for Mapbox API layer
https://mapbox.github.io/mapbox-sdk-cs/
Other
20 stars 11 forks source link

Tile Caching #66

Open isiyu opened 7 years ago

isiyu commented 7 years ago

Starting this ticket to track tile caching. @BergWerkGIS

Tier 1: In memory tile caching Tier 2: file system tile caching Tier 3: selected region tile caching (based on mobile)

david-rhodes commented 7 years ago

And as a reminder: this may need to persist in both the cs and unity layers, with a way to link the two. For example, we might want to cache Texture2d in Unity to avoid destroying and regenerating. This would be a huge source of memory fragmentation in a slippy map. :(

wilhelmberg commented 7 years ago

And as a reminder: this may need to persist in both the cs and unity layers, with a way to link the two.

To be discussed:

I'm not sure if linking the caches makes sense as they serve different purposes:

All kinds of requests (VTs, raster tiles, geocoding, directions) pass through mapbox-sdk-cs's FileSource/HTTPRequest. I think if/how to additionally cache the processed response data lies within the responsibility of the client library - mapbox-unity-sdk in this case.

For mapbox-sdk-cs I'm thinking about just a Dictionary<url, raw response byte[]> and maybe exposing a ClearCache() in FileSource. Or maybe two lists (List<url>, List<response>) to make managing cache size easier.


mapbox-sdk-cs:


I think plan of attack could be:

david-rhodes commented 7 years ago

@BergWerkGIS Thanks for the writeup. Please let me clarify what I meant by "linking" the two cache layers. Here's an example scenario:

I've created a raster slippy map. Tile response data (raw bytes) is cached by distance relative to camera or player (some position). As you pan the map, the tile rendering may be "disabled," but the raw data is still in memory. However, we also want to preserve both the game objects (representing the tile itself--likely with a quad mesh) and the `Texture2D`. In the case that the user now pans back to a location that is cached, we want to apply a cached `Texture2D` to the tile, rather than rebuilding from the raw byte data again.

In this case, do we just share keys across dictionaries for each caching implementation? This is slightly related to your question:

Does it even make sense to cache all (successful) responses?

Perhaps we should abstract caching such that different requests (tiles) are cached differently. Does it make sense to cache raw byte data for a raster tile when we can cache a Texture2D instead? However, it makes more sense to cache the raw data for a vector tile than individual meshes or JSON data. Can we abstract this with interfaces or generics? Developers should be able to implement their own caching strategies, but we can provide a few basic implementations.

Maybe this could be achieved by making a specific FileSource for each type of tile? We don't need just one FileSource as I have coded, so we can be flexible here.

Edit: Another option may be to pass in the object that is making the request and use that as a key. This is less ideal because we would have to rely on casting to handle specific types.

wilhelmberg commented 7 years ago

@david-rhodes I think we have two different requirements on two different levels:

mapbox-sdk-cs doesn't care if/how its clients cache responses. It just returns the response from the cache if the same request gets issued more than once.

Nevertheless I'm thinking about implementing a similar concept like we had before:

Your outlined scenario could work like this:

Although I'm not sure that makes sense as getting to the cached Texture2d would mean issuing the request url again.

To summarize I think mapbox-unity-sdk should implement its own caching mechanism specifically designed for Unity objects. Although it could derive from ICache of course.

If your concern is memory usage I think caching raw response data can be neglected in comparison to caching Unity objects: a few KB vs several MB

david-rhodes commented 7 years ago

Although I'm not sure that makes sense as getting to the cached Texture2d would mean issuing the request url again.

But wouldn't you want your originating request to look identical every single time, regardless if it's cached behind the scenes? To the client, the cache is mostly invisible, right? If I'm making a slippy map and requesting a tile, I shouldn't care if the tile was already fetched or not.

Although it could derive from ICache of course.

Great, this seems like it would be just fine.

If your concern is memory usage I think caching raw response data can be neglected in comparison to caching Unity objects

Well, this is true for most things. Unfortunately, building and destroying Texture2d is a great way to expand the heap and fragment memory. It also takes significant time to load byte data into a texture. I would be curious to know the size difference in raw byte data versus Texture2d memory cost for a raster tile, though.