diff options
Diffstat (limited to 'chromium/docs/website/site/developers/design-documents/cookie-split-loading/index.md')
-rw-r--r-- | chromium/docs/website/site/developers/design-documents/cookie-split-loading/index.md | 189 |
1 files changed, 0 insertions, 189 deletions
diff --git a/chromium/docs/website/site/developers/design-documents/cookie-split-loading/index.md b/chromium/docs/website/site/developers/design-documents/cookie-split-loading/index.md deleted file mode 100644 index 2f7c2d93d4e..00000000000 --- a/chromium/docs/website/site/developers/design-documents/cookie-split-loading/index.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -breadcrumbs: -- - /developers - - For Developers -- - /developers/design-documents - - Design Documents -page_name: cookie-split-loading -title: cookie-split-loading ---- - -Currently, the CookieMonster cookie store is initialized by reading in the -cookies from the backing store in a large lump on first access. This is bad for -several reasons: - -* It violates the principle that we shouldn't do blocking operations - on the IO thread. -* It contributes to perceived user startup time in if a session is - being restored (which requires URL accesses, which result in - CookieMonster accesses). -* It contributes to variation in web page loading, as the first web - page takes substantially longer than later ones. - -This problem is tracked in [Issue 52909](http://crbug.com/52909). This document -sketches out a proposed solution to this problem. - -**Requirements** - -* Minimize startup time (including startup time which includes session - restore, i.e. CM access). -* Minimize stalling of individual set/get cookies. - -I believe that these requirements imply: - -* Basic startup cannot be gated on loading all cookies from persistent - backing store. -* Individual page loads cannot be gated on loading the entire cookie - store from persistent backing store. Ideally, individual page loads - would only load the cookies from persistent backing store that are - needed for that page. -* Full persistent store load should be initiated at startup, but in - the background not blocking any processes (as having cookies loaded - in memory will result in absolute minimum latency). - -**Notes on synchronous vs. asynchronous interfaces to the CookieMonster** - -(See [Issue 68657](http://crbug.com/68657)) - -Generally, services on the IO thread provide asynchronous interfaces with -callbacks, to avoid the IO thread becoming a bottleneck in providing services -for other threads. For all requests after the initial one, the CookieMonster -follows this rule and does not block; all information required for all -CookieMonster APIs is in memory. However, the first call to the CookieMonster -triggers loading in of the entire persistent backing store, done on-thread, -which means that the IO thread blocks on disk operations on the first request to -a CookieMonster with a backing store. - -Giving the CookieMonster an asynchronous interface is a large task, not because -of the internal structure of the Cookie, but because of the large number of -callers, all of whom would need to be adapted to the new interface. Issue -<xxx> tracks this task. - -In an ideal world, the current design would not be dependent on async -CookieMonster interfaces. However, a key part of this design is breaking up the -loading of the backing store into indepedent pieces, using Task objects, which -are spawned off asynchronously in the backing in the absence of incoming -reuqests to laod the backing store database. Combining this with a synchronous -interface for those reuqests that need backing store loads would mean doing one -of: - -* Loading data inline (in the IO thread) when it is needed for a - particular reuqest. This would probably mean that all load tasks - would need to be on the IO thread. -* Completely blocking any IO thread activity while waiting for - responses from the DB thread for data load-in. This violates one of - the basic principles of the IO thread (though in theory it's no - worse than what we're doing now). -* Running nested message loops, and carefully tracking which requests - corresponded to which nesting level of the message loop. If request - B were run while request A had an outstanding load message to the DB - thread, this means that request A would be blocked on the completion - of request B (because the stack couldn't unwind until that point). - -None of these options is particularly appealing. Thus it's preferred that this -work be done after the CookieMonster has been converted over to having an async -interface. The rest of this design assumes such an interface. - -\[Note that it would be relatively easy to layer an asynchronous interface (if -not behavior) on top of the current synchronous interface; the async trigger -would wrap the sync call and a PostTask(self) for the callback. This could allow -incremental changes to the various callers. When all callers had been converted, -the sync interface could be removed and the async interface made to behave in a -non-blocking manner. \] - -**High Level Design** - -The cookie monster will get an additional data structure, indexed by domain key -(currently eTLD+1) indicating whether or not a particular domain key's set of -values has been loaded. Incoming requests (either set of get) will trigger the -loading of the domain key(s) required for those requests if they have not yet -been loaded. In these cases, the incoming request will block (as it currently -does if the backing store hasn't been loaded). All actual database accesses will -occur on the DB thread. - -At CookieMonster construction, a background operation will be invoked to load -the entire cookie store. This will run on the database thread, and will break -down into a series of tasks (T) marks each separate task: - -* (T) Get the list of domain keys contained in the persistent backing - store. -* For each key: - * (T) Load all data from that key into memory - * (T -- IO thread) Incorporate that loaded data into the cookie - monster and mark that key as loaded. - -These are broken up into indiviudal tasks both to avoid freezing the DB thread, -and to allow loads of specific keys triggered by particular web page access to -"jump the queue" and get pulled in earlier. - -**Routine Flow Outline** - -The primary routines and data structures involved in this design are sketched -out below. - -[<img alt="image" -src="/developers/design-documents/cookie-split-loading/objects.svg">](/developers/design-documents/cookie-split-loading/objects.svg) - -There are two basic "ropes" (since they're potentially cross-thread) of routine -invocation: the initial spawn of loading of all of the cookies, and the -load-on-demand triggerred by specific requests to the cookie monster. - -The initial spawn occurs from the CookieMonster constructor -> -SQLitePersistentCookieStore::SpawnFullLoad -> -SQLitePersistentCookieStore::BackingStore::SpawnFullLoad. Once the rope has -reached the DB thread, a full list of all the keys in the SQLite DB is loaded -and stored in BackingStore. Then SpawnFullLoad does a self-dispatch (to the DB -thread) of a ChainLoadKeyCookies task for the first key in the list. -ChainLoadKeyCookies will call LoadKeyCookies (which will load in the cookies -associated with that key from the backing store and notify the CookieMonster of -that load) and will then self-dispatch another instance of ChainLoadKeyCookies. -When the last entry in the key list is loaded, ChainLoadKeyCookies will return -without any action. This will (incrementally, allowing other tasks to run on the -DB thread) load all the cookies. - -If a request comes into the CookieMonster while this chain is executing, it will -check all_loaded_ and keys_loaded_ to detemrine that the relevant data for the -request has not been loaded (if the relevant data has already been loaded, it -will execute the in-memory lookup inline as current and call the callback with -the information). It will then register the callback and operation information -into the key->callback mapping. If that is the first registration of that -key, it will call SQLitePersistentCookieStore::LoadKeyCookies, which will -dispatch an invocation to the DB thread of -SQLitePersistentCookieStore::BackingStore::LoadKeyCookies. If LoadKeyCookies -determines that the key requested has already been loaded (race with above -chain), it will simply exit. - -The tricky part of this design is making sure that there are no races that -result in dangling requests. The invariants that guarantee that this doesn't -happen are: - -* The first entry in the keys->callback table is always correlated - with a LoadKeyCookies dispatch to the DB thread. -* That entry/dispatch will only happen if no previous CompleteLoad for - that key has already arrived. -* The only case in which a LoadKeyCookies dispatch will not result in - a later CompleteLoad dispatch is if a previous CompleteLoad dispatch - for that cookie has already been sent. - -So it's possible for a LoadKeyCookies() dispatch to not result in a -CompleteLoad() being sent back, but only if there's already one in transit. -Thus, if a callback is registered in the keys->callback table, it will be -executed with maximum latency round trip to DB thread + queue wait time + load -time. - -**Object Lifetime Relationships** - -\[Will Chan take note :-}.\] - -Both CookieMonster and PersistentCookieStore are RefCountedThreadSafe objects. -The CookieMonster keeps a reference to the PersistentCookieStore in its store_ -pointer; this guarantees that the store lives as long as the Monster does. - -Both SpawnFullLoad and LoadKeyCookies will take as arguments scoped_refptrs on -the CookieMonster which the PersistentCookieStore (or its backing store) will -use for callbacks. These references will guarantee that the CookieMonster stays -alive for the duration of the callback. - -If the CookieMonster needs to be torn down, it will call an abort() routine on -the PersistentCookieStore, which will break the chain load and release the -scoped_refptr<> held on the CookieMonster by that chain load.
\ No newline at end of file |