-
Notifications
You must be signed in to change notification settings - Fork 85
Discuss API refinements, including caching #73
Comments
The new branch for working on this is at mapbox:issue73 |
Something about upgrading to Xcode 5.1 yesterday seems to have messed up the maps entitlement for the new OS X demo app (the old MBXMapKit 0.1.0 demo app still works though). Probably this is just a local provisioning profile issue on my development box, but it may pop up elsewhere. |
The Xcode provisioning profile thing for the OS X demo seems to be fine now. I did end up committing some changes to the project file as part of getting it working again. |
Based on my experimenting so far, it doesn't seem to be possible to conveniently determine when the data from an NSURLSession data session task came from cache (vs an HTTP download) just by looking at the response. That's inconvenient, because I want to gather statistics about cache hits and misses in order to determine if, and how well, caching strategies are working. The one option I can see so far is to implement |
The NSURLSessionDataDelegate idea didn't work because, as Apple's documentation explains, "If you create a task using a method that takes a completion handler block, the delegate methods for response and data delivery are not called." |
I'm hitting a world of pain as I try to verify what NSURLCache + NSURLSession are actually doing in response to my requested cache and session configurations. My suspicion is that none of my NSURLSession requests are actually getting served from cache, and instead they are always resulting in new HTTP requests. The thing that concerns me is that, as far as I can tell, all the responses I'm getting are In order to get more visibility into, and control over, what happens during network requests, it looks like I might need to stop using data tasks with completion handlers and come up with an alternate approach based on implementing the NSURLSessionDelegate, NSURLSessionTaskDelegate, and NSURLSessionDataDelegate protocols. |
I figured out a way to verify that tiles and JSON are definitely getting written to cache, at least some of the time, but I still haven't found a way to tell if and when subsequent requests are getting served from cache. On my iPhone, the current cache configuration creates a |
I've been running my phone's traffic through Charles Proxy and experimenting with setting cache policies like this:
My conclusions are:
|
Just in case it's not clear, this has to do with whether tiles are missing and going all the way back to the backend render server, or if they are hitting and cached as rasters in the CDN. |
I'm pretty close to convinced it's not possible to distinguish between an NSURLHTTPResponse that comes from a local cache hit and one that comes fresh off an HTTP connection. A bit ago I wrote,
and now I'm pretty sure I misunderstood the purpose of NSCachedURLResponse. As far as I can tell, it is only used with After some time in the debugger looking at |
@incanus re caching headers... yeah, all the server side stuff is fairly straightforward. I've been searching for any hints of about whether my responses are hits or misses from the local cache, and I'm just using this issue to take some notes. |
…nable a way of counting api hits. However, there seems to be no way of distinguishing between a local cache hit response and a fresh response from the API, so it seems like my notification mechanism can’t actually be completed to serve its intended purpose.
Note to self: for persistent offline tile storage, Justin's recommended approach is: don't impose any arbitrary upper limit on the number of tiles it will attempt to download, and do provide a delegate callback which gives progress updates on percent of total completion. Also, I should take a look at RMTileCache and its delegate in the sdk. |
As I'm getting ready to take a swing at background tile downloading for offline maps, I see there's been a fair amount of relevant discussion over in the iOS SDK issues:
|
Apple's recommendations about directories for storing app data and how to exclude files from iCloud backups: |
Status update summarizing my recent commits above:
The status column of the resources table is how MBXOfflineMapDownloader will keep track of which urls have been processed and which ones still need to be requested. Building the mechanism to do that is next up. |
… status info from the resource table will be frequently read and updated, but the blobs only need to be written. This change aims to reduce the volume of changes to the resources table since it will be read frequently.
The next step is to build a pipeline for reading some urls from the db, putting those urls in the download queue, writing the downloaded files back to the db, and keeping the process rolling with additional batches of urls until everything has been downloaded. Building that pipeline is going to take some thought about how to balance the following constraints and questions in a reasonable way, according to the "good enough" principle:
|
You may also find use in exploring hosts |
With the maximum connections per host thing, I think that just using NSURLSession will work fine and there aren't really any problematic questions at that level (i.e. how do we download 4/8/16 files at once). It gets more complicated to make sure that NSURLSession consistently has a reasonable number of urls waiting in its queue to be downloaded. I'm expecting that the NSURLSession will be managing a download queue with a typical backlog of perhaps tens of items waiting to be downloaded in parallel. On the other hand, there might be a backlog in the sqlite offline map database of 1,000 (or 10,000!) items waiting to be downloaded. Throwing 10,000 urls at an NSURLSession seems like a pretty good way to cause memory problems, and on the other end, letting NSURLSession repeatedly drain the backlog down to nothing will lead to lots of time when less than the full number of possible simultaneous downloads are going at once (i.e. takes longer and uses more power). I'm thinking the solution will look like two queues, the small one (NSURLSession) will be for the purpose of keeping simultaneous downloads going while the radio is turned on. The larger one (offline map sqlite db plus some logic) will be to make sure NSURLSession has a backlog that's not too large and not too small, for the purpose keeping memory usage and disk activity within reasonable limits. |
Note to self: To get some order of magnitude numbers for how many tiles people might try downloading, try calculating the tiles for these regions, zoom 0-17:
|
I just hit a significant milestone. Basically the first draft of my sqlite stuff for offline maps is complete and working. By that I mean I can create a db using an array of urls which need to be downloaded, I can read progress counts out of it, I can read batches of urls (using SELECT... LIMIT) to download, I can write image blobs and status codes back out, I can save the completed db to a unique filename, and I can find and display completed offline map db's on the map. This is progress! The main things left on the todo list for this ticket are:
|
Status update: rough cut at dynamically generating the tile urls is working, but the marker icon stuff needs work in a couple different ways. When I hardcoded a url for a marker icon that I knew was in the markers.geojson, it didn't show up on the map, and that's a bit puzzling. Also, on the MBXOfflineMapDownloader side, I need to implement something to download and parse the marker geojson at the time that the list of urls is being created. |
Offline maps work on iOS, markers included! |
Handy pre-PR link comparing the |
This seems really well thought-out, @wsnook! I can't possibly hope to totally grok 65 commits and 32 changed files with 4,961 additions and 5 deletions just yet, particularly the whole functionality of
Main comments (voice)
Minor comments (online)
|
The Plan from voice chat just now with @incanus... I need to:
|
I'm closing this to be continued over at #79. |
Over at issue #61 we considered a refactored design for asynchronously loading TileJSON, and at pull request #71 we discussed my issue61 branch with a new approach to solving problems around the asynchronous TileJSON stuff.
The conclusion from #71 seems to be that the general approach in the issue61 branch is sound, but it needs to be packaged within an API which feels consistent with Apple's API's in general, and MKMapKit in particular. So this ticket is for discussing refinements to the API. One of the big open questions is what the caching will look like.
My plan for the moment is:
Once the delegate protocol implementations and caching stuff are in good order,work on simplifying, renaming, and otherwise polishing up the remaining API.I'm guessing this iteration will reach a good stopping point by approximately March 20th (next Thursday).
The text was updated successfully, but these errors were encountered: