Closed
Bug 980081
Opened 11 years ago
Closed 11 years ago
Cache consumer info/homepage/category landing API responses with localStorage
Categories
(Marketplace Graveyard :: Code Quality, defect, P2)
Tracking
(Not tracked)
RESOLVED
FIXED
2014-04-01
People
(Reporter: clouserw, Assigned: cvan)
References
Details
(Keywords: perf)
One of the takeaways from MWC was that the marketplace is slow to start, both warm and cold. Cold starts is something we'll look at elsewhere (that is, we'll finish becoming a real packaged app) but warm starts is something we should fix.
Cvan has done some investigation in this area (please feel free to do more) and his recommendations is that we cache all our downloads (API responses, images) in IndexedDB locally so we can retrieve it quickly. It's been suggested we use https://github.com/mozilla/localForage (more: https://hacks.mozilla.org/2014/02/localforage-offline-storage-improved/ ).
Dethe - please work with cvan to come up with a plan to address this and then implement. Thanks.
Assignee | ||
Comment 1•11 years ago
|
||
* We're using an in-memory cache (just a simple JavaScript object) for caching XHR requests, keyed off of API URLs.
* We're also doing browser caching on GET API requests (https://github.com/mozilla/fireplace/blob/master/hearth/media/js/routes_api.js#L3-L8 and https://github.com/mozilla/fireplace/blob/master/hearth/media/js/routes_api.js#L18), but it's based on a max-age of 3 minutes.
* We're also sending down ETag headers, and the browser's doing If-None-Match header checks, but that doesn't eliminate the time to first byte. <-- What we're trying to solve.
I had a patch that uses our persistent request cache (https://github.com/mozilla/fireplace/blob/master/hearth/media/js/requests.js#L104 and https://github.com/mozilla/fireplace/blob/master/hearth/media/js/cache.js#L46) when caching XHR requests. (Notice that currently our persistent storage is currently using localStorage.)
# Before
# For all users
1. We load the home page.
2. `defer` blocks get called asynchronously, `requests.get` gets called, cache miss, fire off XHRs.
3. Responses of XHRs get cached *in memory*.
4. Navigate away from page, come back to homepage and XHRs are cached in memory, so we just re-render the templates from that.
5. Refresh the page, and the cache is gone.
# After
## For a page load with an empty cache
1. We load the home page.
2. `defer` blocks get called asynchronously, `requests.get` gets called, cache miss, fire off XHRs.
3. Responses of XHRs get cached *in IndexedDB* (keyed off of API URL, ETag header [and TTL if we want to expire after some time]).
4. Navigate away from page, come back to homepage and XHRs are cached in memory, so we just re-render the templates from that.
5. Refresh the page, and the cached XHRs are already in the persistent request cache (IndexedDB) so we can render the template without needing to wait for the XHRs to finish.
## For subsequent page loads
1. We load the home page.
2. `defer` blocks get called asynchronously, `requests.get` gets called, persistent cache hit (assuming the TTL hasn't caused a cache expiry yet), but *continue to fire off XHRs asynchronously in the background*.
3. Render the templates immediately not that we have the XHR responses from the request cache.
4. For each new XHR response, if the response's ETag header is different from that of the cached copy's, then rewrite the cached entry for that API URL in the persistent (IndexedDB) and in-memory caches with the new ETag, new response, and new TTL.
5. Do not re-render template, but on subsequent page refreshes the templates will reflect the data that we got asynchronously when the XHRs were getting updated in the background.
The best part? The user doesn't have to wait several seconds before interacting with the page. Even when we move our API responses to the CDN, these are the best times Akamai is able to give us for the homepage API requests: 1.25s for the featured API response,108 ms for the popular API response, 57 ms for the category API response.
I've done some work getting this working using localStorage, which I demoed at the Portland work week. It's hiding in one of my dozens of branches; I probably won't ever find it. Anyway, I've used IndexedDB/localForage for other projects; localForage gives you promises and it should really be a cinch to integrate into our request caching.
Questions, suggestions, concerns, things I haven't thought of? Holla.
Assignee | ||
Updated•11 years ago
|
Summary: Cache all our downloads with localForage → Cache our API responses with IndexedDB/localForage
Assignee | ||
Comment 2•11 years ago
|
||
Assignee | ||
Updated•11 years ago
|
Assignee: delza → cvan
Summary: Cache our API responses with IndexedDB/localForage → Cache consumer info/homepage/category landing API responses with localStorage
Target Milestone: --- → 2014-04-01
Assignee | ||
Comment 3•11 years ago
|
||
https://github.com/mozilla/fireplace/commit/51c372a
Desktop:
1. Load the home page.
2. Notice the console logs contain these lines for the two XHRs:
> [req] GETing from cache https://marketplace-dev.allizom.org/api/v1/fireplace/consumer-info/?_user=---&lang=en-US log.js:51
> ...
> [req] GETing from cache https://marketplace-dev.mozflare.net/api/v1/fireplace/search/featured/?cache=1&cat=&lang=en-US®ion=us&vary=0
3. Refresh the home page.
4. Notice the console logs contain now contain these lines for the two XHRs:
> [req] GETing from cache https://marketplace-dev.allizom.org/api/v1/fireplace/consumer-info/?_user=---&lang=en-US log.js:51
> [req] GETing https://marketplace-dev.allizom.org/api/v1/fireplace/consumer-info/?_user=---&lang=en-US
> ...
> [req] GETing from cache https://marketplace-dev.mozflare.net/api/v1/fireplace/search/featured/?cache=1&cat=&lang=en-US®ion=us&vary=0
> [req] GETing https://marketplace-dev.mozflare.net/api/v1/fireplace/search/featured/?cache=1&cat=&lang=en-US®ion=us&vary=0
5. Proceed to click around to various pages, refreshing, going and back and forth in histroy, etc. Please make sure everything still works. And upon refreshing, the pages should load immediately but then proceed to update the cache in the background.
Side notes:
- Please verify that we don't use the cached API responses when loading https://marketplace-dev.allizom.org/?cache=false
- Please verify these flows on mobile and on desktop. Relaunching the app and refreshing the web site on desktop should both have the same loading times, as the caching mechanism is the same between app relaunches and page refreshes.
- Please verify these flows on EDGE (64K) and sub-edge (48K or lower).
- Please verify these flows on the homepage and category landing pages. This new caching mechanism does not apply to search pages, app detail pages, app ratings pages, My Apps, etc.
- If you load the homepage or a category page, and its API response is already cached, then it should load immediately and cache the response *once and only once*. If you navigate to another page and come back to that page, we should never make another HTTP request (the logs should continue to say "GETing from cache https://..." and never "GETting https://...".
Please let me know if you have any questions. This is awesome stuff!
And one more thing... make sure your socks are on tight because they're about to be knocked off!
Thank you! =)
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Comment 4•11 years ago
|
||
Please add STR here or mark it with [qa-] if no QA is needed.
Flags: needinfo?(clouserw)
Comment 6•11 years ago
|
||
I don't see the following GET in the console when loading the homepage according to step 2 from comment 3
GETing from cache https://marketplace-dev.allizom.org/api/v1/fireplace/consumer-info/?_user=---&lang=en-US log.js:51
Please see screencast http://screencast.com/t/up0R1nAM
Flags: needinfo?
Assignee | ||
Comment 7•11 years ago
|
||
http://f.cl.ly/items/0H112F0c2k3s392d2Z3G/Screen%20Shot%202014-04-01%20at%201.38.52%20PM.png
You should always see the consumer info XHR. Mat, Mark - ideas?
Flags: needinfo?
You need to log in
before you can comment on or make changes to this bug.
Description
•