Bug 16025 - Re: Web Storage Editor's Draft 28 November 2011 "The use of the storage mutex to avoid race conditions is currently considered by certain implementors to be too high a performance burden, to the point where allowing data corruption is considered preferabl
Summary: Re: Web Storage Editor's Draft 28 November 2011 "The use of the storage mutex...
Status: RESOLVED NEEDSINFO
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: Web Storage (editor: Ian Hickson) (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: ---
Assignee: Ian 'Hixie' Hickson
QA Contact: public-webapps-bugzilla
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-02-18 20:58 UTC by contributor
Modified: 2012-07-25 03:02 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description contributor 2012-02-18 20:58:57 UTC
Specification: http://dev.w3.org/html5/webstorage/
Multipage: http://www.whatwg.org/C#top
Complete: http://www.whatwg.org/c#top

Comment:
Re: Web Storage Editor's Draft 28 November 2011

"The use of the storage mutex to avoid race conditions is currently considered
by certain implementors to be too high a performance burden, to the point
where allowing data corruption is considered preferable. Alternatives that do
not require a user-agent-wide per-origin script lock are eagerly sought
after."

If I understand the issue correctly, NO actual locks are required to ensure
both valid read and write transactions.

There are multiple solutions. An example eventually-consistent solution might
be:

(1) Writes of each process are limited to a store assigned to that process.
(1.a) Those stores do not need to be lock-protected, as there is only one
writer. 
(1.b) However, there may be more than one reader, so the write must be a
complete transaction. That can be accomplished by having a buffered write
queue and a single (in-memory, but ultimately file-backed) value which
represents the index valid buffer. (The size of this value determined by the
size of an atomic write on the architecture e.g. 32 bit atomic integer writes
would be the lowest-common-denominator on common architectures like x86, PPC,
ARM)
(1.c) That index would be continuously incrementing per-session, per-process,
per-write. In theory, the per-session write limits (and buffer counts) are
then unbounded, but the spec does not provide any limits anyway and in
practice, reasonable limits can be made and edge cases (e.g. very long
lasting, partially opened reads from another process) accounted for
separately.
(2) No lock is needed on read, as reads from any process would read through
the integer-ids (incrementing buffer indices) of each other process and use
those to deference last-known-good versions of the value-store. Which are by
(1) guaranteed to not change during the duration of the read (All are
consistent: index, the deferenced value which points to in-memory or
file-store and the final stored value.)

No race conditions, no locks. However, the memory use is higher. But that IS
boundable in practice.

Mike.

Mike Acton <macton@insomniacgames.com>


Posted from: 24.205.74.166
User agent: Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11
Comment 1 Ian 'Hixie' Hickson 2012-07-10 21:26:48 UTC
How would you limit the number of writers to one process, given that there could be two windows open on the same page (and thus reading and writing to the same database) but using different processes?

If you mean that the writes should be queued to a single back-end writer, how do you prevent corruption in a case such as the following? What should the values read be where I have the question marks? Assume the two columns are happening in different processes but exactly at the same time, though they can be reading and writing via a single backend process if that helps.

   Window 1                      Window 2

   read key "test" (value=0)     read key "test" (value=0)

   write value=1 to key "test"   write value=1 to key "test"
   write value=a to key "v1"     write value=b to key "v1"
   write value=x to key "ra"     write value=y to key "rb"

   read key "test" (value=1?)    read key "test" (value=1?)
   read key "v1" (value=?)       read key "v1" (value=?)
   read key "ra" (value=?)       read key "ra" (value=?)
   read key "rb" (value=?)       read key "rb" (value=?)

   spin the event loop           spin the event loop

   read key "test" (value=1?)    read key "test" (value=1?)
   read key "v1" (value=?)       read key "v1" (value=?)
   read key "ra" (value=?)       read key "ra" (value=?)
   read key "rb" (value=?)       read key "rb" (value=?)