-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Re-request expired resources #3944
Conversation
ready for 👀 🚦 |
|
||
if (this._cacheTimers[coord.id]) { | ||
clearTimeout(this._cacheTimers[coord.id]); | ||
delete this._cacheTimers[coord.id]; |
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.
Even though delete
is clearer, this might be a case where it's better to use this._cacheTimers[coord.id] = undefined
, because this method is (relatively) hot and, as I understand it, delete
causes V8 to re-compute an object's hidden class.
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.
Oo @anandthakker thank you — did not know this, googled a little hole for myself to understand further: googleapis/google-api-nodejs-client#375
@@ -396,14 +411,19 @@ class SourceCache extends Evented { | |||
tile = this._cache.get(wrapped.id); | |||
if (tile) { | |||
tile.redoPlacement(this._source); | |||
if (this._cacheTimers[wrapped.id]) { | |||
clearTimeout(this._cacheTimers[wrapped.id]); | |||
delete this._cacheTimers[wrapped.id]; |
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.
See above re: delete
if (tileExpires) { | ||
this._cacheTimers[id] = setTimeout(() => { | ||
this._cache.remove(id); | ||
delete this._timers[id]; |
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.
should this be this._cacheTimers[id]
?
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 should, yes 🙇♀️
remove(key: string) { | ||
if (!this.has(key)) { return this; } | ||
|
||
this.onRemove(this.data[key]); |
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.
In add()
, it looks like this.onRemove()
gets called after the item is deleted from this.data
, whereas here, it's getting called before; being inconsistent could cause problem at some point.
Also, a question: am I missing something, or does cache.get()
actually also remove the item? If that's so, is remove()
redundant? (Although, admittedly, I normally would not expect a method called get()
to have a side effect...)
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.
cache.get
removes an item from the cache and returns it, so there is some repeated code here, and we could use cache.get
to delete tiles from the cache, but then it's returning expiring tiles to nowhere and would be less intuitive in code (when cached tile's timer expires, retrieve it from the cache … vs when cached tile's timer expires, remove it from the cache). 😕
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.
Yeah, fair enough. I'd actually be okay with "returning expired tiles to nowhere" (i.e. the calling code need not actually store the return value), BUT because it's called get
I agree it would look pretty weird:
// oh, we need to remove the cache entry now, so
cache.get(id)
// cool, moving on
I sort of wonder if we should just rename LRUCache#get
to LRUCache#remove
-- that way, whether the calling code actually uses the return value or not, it is very clear that you're removing the entry from the cache.
clearTimeout(this._cacheTimers[coord.id]); | ||
delete this._cacheTimers[coord.id]; | ||
this._setTimers(coord.id, cachedTile); | ||
} |
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 looks to me like we always do addTile()
with any nonempty return value from this method -- since that's the case, and since we have equivalent logic for removing cacheTimer / adding timer already in addTile, is it possible that we could avoid redundancy by only doing it in addTile?
@lbud changes LGTM! All I have left are a couple nits on naming/clarity that I should have thought of earlier:
^ this is all motivated by the notion that caching logic in general and SourceCache in particular tend to be hard to read/reason about and easy to mess up later (for me, 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.
@lbud Marking as approved since my remaining comments are all opinion/judgment calls
I'd be okay with renaming it, although I instinctively think it's fine to keep both: adding
I started doing this, but hesitated because of this part of |
* set cache timers in SourceCache + remove tiles from the cache when they expire * handle for setting/resetting timers when moving from SourceCache <-> LRUCache
* Avoid 'delete's so as to not re-compute hidden classes * Remove redundant cache timer clearing logic from 'findLoadedParent' * Consistify lru_cache's order of operations re deleting
Ah, yeah I see what you mean. 👍 |
Very cool stuff - excited about this. We have a use case for this right now, great to see it is in action! |
Since I upgraded to the version that include that feature, I started getting bunch of errors It is coming from mapbox-gl-js/src/source/source_cache.js Line 149 in b9e10b9
I am sorry, I can not point you out to any gist that shows the errors. I am still investigating. Wondering if someone has that same issue? I am using the new smart Thanks for MapBox GL. |
@karlguillotte thank you for reporting this. Could you please open a new issue describing this bug? I know you said that you're still investigating -- if you're able to provide a minimal example demonstrating the problem, that would greatly improve our chances of to diagnosing and solving it. |
I have this bug also. Working on tracking down exactttllyy what's going on. |
The root cause appears to be this line: https://github.com/mapbox/mapbox-gl-js/blob/master/src/source/source_cache.js#L438 The issue occurs when (Problem seems to be because of the implementation of |
Closes #1947.
This PR modifies
ajax#getArrayBuffer
to requestCache-Control
andExpires
headers.SourceCache
maintains timers for tiles with set expiry dates for both active and cached tiles:Launch Checklist