On Thu, Sep 24, 2009 at 12:20 AM, Jonas Sicking <span dir="ltr">&lt;jonas@sicking.cc&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div><div></div><div>On Wed, Sep 23, 2009 at 10:19 PM, Darin Fisher &lt;<a href="mailto:darin@chromium.org" target="_blank">darin@chromium.org</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt; On Wed, Sep 23, 2009 at 8:10 PM, Jonas Sicking &lt;jonas@sicking.cc&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Wed, Sep 23, 2009 at 3:29 PM, Jeremy Orlow &lt;<a href="mailto:jorlow@chromium.org" target="_blank">jorlow@chromium.org</a>&gt; wrote:<br>
&gt;&gt; &gt; On Wed, Sep 23, 2009 at 3:15 PM, Jonas Sicking &lt;jonas@sicking.cc&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; On Wed, Sep 23, 2009 at 2:53 PM, Brett Cannon &lt;<a href="mailto:brett@python.org" target="_blank">brett@python.org</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt; &gt; On Wed, Sep 23, 2009 at 13:35, Jeremy Orlow &lt;<a href="mailto:jorlow@chromium.org" target="_blank">jorlow@chromium.org</a>&gt;<br>
&gt;&gt; &gt;&gt; &gt; wrote:<br>
&gt;&gt; &gt;&gt; &gt;&gt; What are the use cases for wanting to store data beyond strings (and<br>
&gt;&gt; &gt;&gt; &gt;&gt; what<br>
&gt;&gt; &gt;&gt; &gt;&gt; can be serialized into strings) in LocalStorage?  I can&#39;t think of<br>
&gt;&gt; &gt;&gt; &gt;&gt; any<br>
&gt;&gt; &gt;&gt; &gt;&gt; that<br>
&gt;&gt; &gt;&gt; &gt;&gt; outweigh the negatives:<br>
&gt;&gt; &gt;&gt; &gt;&gt; 1)  From previous threads, I think it&#39;s fair to say that we can all<br>
&gt;&gt; &gt;&gt; &gt;&gt; agreed<br>
&gt;&gt; &gt;&gt; &gt;&gt; that LocalStorage is a regrettable API (mainly due to its<br>
&gt;&gt; &gt;&gt; &gt;&gt; synchronous<br>
&gt;&gt; &gt;&gt; &gt;&gt; nature).  If so, it seems that making it more powerful and thus more<br>
&gt;&gt; &gt;&gt; &gt;&gt; attractive to developers is just asking for trouble.  After all, the<br>
&gt;&gt; &gt;&gt; &gt;&gt; more<br>
&gt;&gt; &gt;&gt; &gt;&gt; people use it, the more lock contention there&#39;ll be, and the more<br>
&gt;&gt; &gt;&gt; &gt;&gt; browser UI<br>
&gt;&gt; &gt;&gt; &gt;&gt; jank users will be sure to experience.  This will also be worse<br>
&gt;&gt; &gt;&gt; &gt;&gt; because<br>
&gt;&gt; &gt;&gt; &gt;&gt; it&#39;ll be easier for developers to store large objects in<br>
&gt;&gt; &gt;&gt; &gt;&gt; LoaclStorage.<br>
&gt;&gt; &gt;&gt; &gt;&gt; 2)  As far as I can tell, there&#39;s no where else in the spec where<br>
&gt;&gt; &gt;&gt; &gt;&gt; you<br>
&gt;&gt; &gt;&gt; &gt;&gt; have<br>
&gt;&gt; &gt;&gt; &gt;&gt; to serialize structured clone(able) data to disk.  Given that<br>
&gt;&gt; &gt;&gt; &gt;&gt; LocalStorage<br>
&gt;&gt; &gt;&gt; &gt;&gt; is supposed to throw an exception if any ImageData is contained and<br>
&gt;&gt; &gt;&gt; &gt;&gt; since<br>
&gt;&gt; &gt;&gt; &gt;&gt; File and FileData objects are legal, it seems as though making<br>
&gt;&gt; &gt;&gt; &gt;&gt; LocalStorage<br>
&gt;&gt; &gt;&gt; &gt;&gt; handle structured clone data has a fairly high cost to implementors.<br>
&gt;&gt; &gt;&gt; &gt;&gt;  Not to<br>
&gt;&gt; &gt;&gt; &gt;&gt; mention that disallowing ImageData in only this one case is not<br>
&gt;&gt; &gt;&gt; &gt;&gt; intuitive.<br>
&gt;&gt; &gt;&gt; &gt;&gt; I think allowing structured clone(able) data in LocalStorage is a<br>
&gt;&gt; &gt;&gt; &gt;&gt; big<br>
&gt;&gt; &gt;&gt; &gt;&gt; mistake.  Enough so that, if SessionStorage and LocalStorage can&#39;t<br>
&gt;&gt; &gt;&gt; &gt;&gt; diverge<br>
&gt;&gt; &gt;&gt; &gt;&gt; on this issue, it&#39;d be worth taking the power away from<br>
&gt;&gt; &gt;&gt; &gt;&gt; SessionStorage.<br>
&gt;&gt; &gt;&gt; &gt;&gt; J<br>
&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; &gt; Speaking from experience, I have been using localStorage in my PhD<br>
&gt;&gt; &gt;&gt; &gt; thesis work w/o any real need for structured clones (I would have<br>
&gt;&gt; &gt;&gt; &gt; used<br>
&gt;&gt; &gt;&gt; &gt; Web Database but it isn&#39;t widely used yet and I was not sure if it<br>
&gt;&gt; &gt;&gt; &gt; was<br>
&gt;&gt; &gt;&gt; &gt; going to make the cut in the end). All it took to come close to<br>
&gt;&gt; &gt;&gt; &gt; simulating structured clones now was to develop my own compatibility<br>
&gt;&gt; &gt;&gt; &gt; wrapper for localStorage (<a href="http://realstorage.googlecode.com" target="_blank">http://realstorage.googlecode.com</a> for those<br>
&gt;&gt; &gt;&gt; &gt; who care) and add setJSONObject() and getJSONObject() methods on the<br>
&gt;&gt; &gt;&gt; &gt; wrapper. Works w/o issue.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Actually, this seems like a prime reason *to* add structured storage<br>
&gt;&gt; &gt;&gt; support. Obviously string data wasn&#39;t enough for you so you had to<br>
&gt;&gt; &gt;&gt; write extra code in order to work around that. If structured clones<br>
&gt;&gt; &gt;&gt; had been natively supported you both would have had to write less<br>
&gt;&gt; &gt;&gt; code, and the resulting algorithms would have been faster. Faster<br>
&gt;&gt; &gt;&gt; since the browser can serialize/parser to/from a binary internal<br>
&gt;&gt; &gt;&gt; format faster than to/from JSON through the JSON serializer/parser.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Yes, but since LocalStorage is already widely deployed, authors are<br>
&gt;&gt; &gt; stuck<br>
&gt;&gt; &gt; with the the structured clone-less version of LocalStorage for a very<br>
&gt;&gt; &gt; long<br>
&gt;&gt; &gt; time.  So the only way an app can store anything that can&#39;t be JSONified<br>
&gt;&gt; &gt; is<br>
&gt;&gt; &gt; to break backwards compatibility.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; On Wed, Sep 23, 2009 at 3:11 PM, Jonas Sicking &lt;jonas@sicking.cc&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; On Wed, Sep 23, 2009 at 1:35 PM, Jeremy Orlow &lt;<a href="mailto:jorlow@chromium.org" target="_blank">jorlow@chromium.org</a>&gt;<br>
&gt;&gt; &gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt; &gt; What are the use cases for wanting to store data beyond strings (and<br>
&gt;&gt; &gt;&gt; &gt; what<br>
&gt;&gt; &gt;&gt; &gt; can be serialized into strings) in LocalStorage?  I can&#39;t think of<br>
&gt;&gt; &gt;&gt; &gt; any<br>
&gt;&gt; &gt;&gt; &gt; that<br>
&gt;&gt; &gt;&gt; &gt; outweigh the negatives:<br>
&gt;&gt; &gt;&gt; &gt; 1)  From previous threads, I think it&#39;s fair to say that we can all<br>
&gt;&gt; &gt;&gt; &gt; agreed<br>
&gt;&gt; &gt;&gt; &gt; that LocalStorage is a regrettable API (mainly due to its synchronous<br>
&gt;&gt; &gt;&gt; &gt; nature).  If so, it seems that making it more powerful and thus more<br>
&gt;&gt; &gt;&gt; &gt; attractive to developers is just asking for trouble.  After all, the<br>
&gt;&gt; &gt;&gt; &gt; more<br>
&gt;&gt; &gt;&gt; &gt; people use it, the more lock contention there&#39;ll be, and the more<br>
&gt;&gt; &gt;&gt; &gt; browser UI<br>
&gt;&gt; &gt;&gt; &gt; jank users will be sure to experience.  This will also be worse<br>
&gt;&gt; &gt;&gt; &gt; because<br>
&gt;&gt; &gt;&gt; &gt; it&#39;ll be easier for developers to store large objects in<br>
&gt;&gt; &gt;&gt; &gt; LoaclStorage.<br>
&gt;&gt; &gt;&gt; &gt; 2)  As far as I can tell, there&#39;s no where else in the spec where you<br>
&gt;&gt; &gt;&gt; &gt; have<br>
&gt;&gt; &gt;&gt; &gt; to serialize structured clone(able) data to disk.  Given that<br>
&gt;&gt; &gt;&gt; &gt; LocalStorage<br>
&gt;&gt; &gt;&gt; &gt; is supposed to throw an exception if any ImageData is contained and<br>
&gt;&gt; &gt;&gt; &gt; since<br>
&gt;&gt; &gt;&gt; &gt; File and FileData objects are legal, it seems as though making<br>
&gt;&gt; &gt;&gt; &gt; LocalStorage<br>
&gt;&gt; &gt;&gt; &gt; handle structured clone data has a fairly high cost to implementors.<br>
&gt;&gt; &gt;&gt; &gt;  Not to<br>
&gt;&gt; &gt;&gt; &gt; mention that disallowing ImageData in only this one case is not<br>
&gt;&gt; &gt;&gt; &gt; intuitive.<br>
&gt;&gt; &gt;&gt; &gt; I think allowing structured clone(able) data in LocalStorage is a big<br>
&gt;&gt; &gt;&gt; &gt; mistake.  Enough so that, if SessionStorage and LocalStorage can&#39;t<br>
&gt;&gt; &gt;&gt; &gt; diverge<br>
&gt;&gt; &gt;&gt; &gt; on this issue, it&#39;d be worth taking the power away from<br>
&gt;&gt; &gt;&gt; &gt; SessionStorage.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Despite localStorage unfortunate locking contention problem, it&#39;s<br>
&gt;&gt; &gt;&gt; become quite a popular API. It&#39;s also very successful in terms of<br>
&gt;&gt; &gt;&gt; browser deployment since it&#39;s available in at least latest versions of<br>
&gt;&gt; &gt;&gt; IE, Safari, Firefox, and Chrome. Don&#39;t know about support in Opera?<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; The more popular it becomes, the more it&#39;s going to hurt UA developers,<br>
&gt;&gt; &gt; web<br>
&gt;&gt; &gt; developers, and users.  I don&#39;t see why this is an argument for making<br>
&gt;&gt; &gt; it<br>
&gt;&gt; &gt; more powerful.<br>
&gt;&gt;<br>
&gt;&gt; How will it hurt UA developers? I think we&#39;re stuck forever to<br>
&gt;&gt; implement the locking mechanism. Adding more datatypes to the API<br>
&gt;&gt; doesn&#39;t mean that we&#39;ll have to implement it more.<br>
&gt;<br>
&gt;<br>
&gt; multi-core is the future.  what&#39;s the opposite of fine-grained locking?<br>
&gt;  it&#39;s not good ;-)<br>
&gt; the implicit locking mechanism as spec&#39;d is super lame.  implicitly<br>
&gt; unlocking under<br>
&gt; mysterious-to-the-developer circumstances!  how can that be a good thing?<br>
&gt; storage.setItem(&quot;y&quot;,<br>
&gt; function_involving_implicit_unlocking(storage.getItem(&quot;x&quot;)));<br>
<br>
</div></div>I totally agree on all points. The current API has big imperfections.<br>
However I haven&#39;t seen any workable counter proposals so far, and I<br>
honestly don&#39;t believe there are any as long as our goals are:<br>
<br>
* Don&#39;t break existing users of the current implementations.<br>
* Don&#39;t expose race conditions to the web.<br>
* Don&#39;t rely on authors getting explicit locking mechanisms right.<br></blockquote><div> </div><div>I agree that there&#39;s no way to &quot;fix&quot; local storage without violating one of these goals.  That&#39;s why I think we should just leave it alone and come up with a better API.  If we keep improving LocalStorage then of course people will continue using it!  (Which, as I mentioned, will only make the problems worse.)  In other words, the more features we add to LocalStorage at this point, the worse we&#39;re making the web platform as a whole.</div>


<div><br></div><div>Just to be super clear: I&#39;m not advocating getting rid of LocalStorage as is.  (Anymore.  :-)  I&#39;m saying that we should leave it as is and come up with a better storage API that all browser vendors can get behind.</div>


<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
But, as imperfect as the current API is, I think the following is a<br>
decent way forward:<br>
<br>
* Allow pages that want the convenience of localStorage to use it. For<br>
multi-process browsers this will mean poor UI *for pages that use<br>
localStorage*. Especially when said pages hold on to localStorage for<br>
a long time.<br>
* Add alternative APIs that don&#39;t suffer from the same problems. More below.<br>
<div><div></div><div><br>
&gt;&gt; &gt; In addition, this argument assumes that Microsoft (and other UAs) will<br>
&gt;&gt; &gt; implement the structured clone version of LocalStorage.  Has anyone (or<br>
&gt;&gt; &gt; can<br>
&gt;&gt; &gt; anyone) from Microsoft comment on this?<br>
&gt;&gt;<br>
&gt;&gt; Given that I&#39;ve never heard microsoft commit to a webstandard, ever, I<br>
&gt;&gt; doubt that we&#39;ll hear anything here. Or that the lack of hearing<br>
&gt;&gt; anything means we can draw any conclusions.<br>
&gt;&gt;<br>
&gt;&gt; &gt; This is not a small feature to add.  Yes, it&#39;s smaller than creating a<br>
&gt;&gt; &gt; new<br>
&gt;&gt; &gt; storage mechanism (that everyone is willing to adopt), but I still think<br>
&gt;&gt; &gt; that&#39;s what we should be looking at.  Rather than polishing a turd.<br>
&gt;&gt;<br>
&gt;&gt; I do think that localStorage is a decent API that developers will want<br>
&gt;&gt; to, and should, use. I think looking into adding a async accessor to<br>
&gt;&gt; get a storage object so that people can use an localStorage-like API<br>
&gt;&gt; while avoiding risks of blocking. This would also allow sharing data<br>
&gt;&gt; between worker threads and the main window.<br>
&gt;<br>
&gt; i think the async callback to get a storage object is an improvement, but<br>
&gt; i&#39;m not sure that it addresses all of the problems.  for example, if a<br>
&gt; worker<br>
&gt; wants to read values from storage, compute, and then put a value into<br>
&gt; storage, it would probably do all of this from the storage callback.  that<br>
&gt; would result in holding the lock for a long time, which would lock out any<br>
&gt; other threads, including non-worker threads.<br>
&gt; the problem here is that localStorage is a pile of global variables.  we are<br>
&gt; trying to give people global variables without giving them tools to<br>
&gt; synchronize<br>
&gt; access to them.  the claim i&#39;ve heard is that developers are not savy enough<br>
&gt; to use those tools properly.  i agree that developers tend to use tools<br>
&gt; without<br>
&gt; fully understanding them.  ok, but then why are we giving them global<br>
&gt; variables?<br>
&gt; there has to be a better answer.<br>
<br>
</div></div>I actually described an potential solution in the thread on worker storage.<br>
<br>
The problem you describe is a worker holding on the the storage for an<br>
very long (indefinite) time, thereby locking out other threads/windows<br>
from accessing the same storage area.This seems inevitable if we want<br>
to prevent race conditions while at the same time not forcing the<br>
complexities of locks onto web developers. The WebDatabase API suffers<br>
from exactly the same problem.<br></blockquote><div><br></div><div>Actually, it&#39;s not the same problem.  When pages access LocalStorage synchronously, it means that entire event loops get can be blocked by one worker.  If instead pages only have asynchronous access (as they do in the WebDatabase API), then the only problem is that their callback will never get called.  Such resource starvation is of course sub-optimal, but at least it won&#39;t affect other pages in the same event loop.</div>


<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
However, we can lessen the problem. By adding multiple storage areas,<br>
we can allow a worker to use one storage area, while allowing other<br>
parties to simultaneously use other storage areas. This way, if a<br>
worker and a window aren&#39;t sharing data at all, they never get in the<br>
way of each other.<br>
<br>
So a very simplistic design would be something like the following:<br>
<br>
getStorageArea(name, callback)<br>
<br>
when called will asynchronously call the callback parameter once the<br>
storage area named by the first parameter becomes available. The<br>
callback receives the storage area as an argument. We would also have<br>
the function<br>
<br>
getMultipleStorageAreas(names, callback)<br>
<br>
Same as above, but names is an array of strings indicating multiple<br>
storage areas that need to be acquired before the callback is called.<br>
The callback receives all the areas in an array as an argument. This<br>
function allows transferring data between multiple storage areas<br>
without risking racing.<br></blockquote><div><br></div><div>These are all good suggestions, but I&#39;m not sure even that API would be powerful enough for developers.</div>
<div><br></div><div>&lt;thought exercise&gt;</div><div>For example, how would you implement an offline webmail app?  Well, my first thought is to make each email a key/value.  But we can&#39;t iterate over ranges of keys, so that won&#39;t work.  Maybe instead we can make each key a folder for our mail?  We could store all the mails in an array.  But that could be a huge amount of data in each key--on the order of hundreds of megabytes for some users.  So, to optimize, I guess we could store the emails in their own keys and then just store large arrays of mail keys in each folder key.  This would also solve the problem of gmail-like &quot;labels&quot; (i.e. a many to one relationship between folders/labels to emails).  Oh yeah, and we&#39;d need to have one key that&#39;s a list of all the folders.</div>


<div><br></div><div>Great.  But now we want to allow offline searching of our emails.  Crap.  Well we can efficiently search arrays with a binary search.  But that takes a while to update.  Well, we can implement a balanced tree for each index and then store it in keys.  And have one key that has a list of all our index keys.  This seems reasonably efficient--as long as the trees don&#39;t get too big.  Even if the implementation is pretty slick, once they get to a certain size, just loading one key into memory could take a while.  Especially since the entire time we&#39;re updating/reading/whatever our keys, we&#39;re either starving other tabs from accessing the data or blocking their event loop.</div>


<div>&lt;/thought exercise &gt;</div><div><br></div><div>So yes: I do think that you can create at least a simple web mail client.  And, as long as the JavaScript engine is fast enough to handle large, complex data structures (without running out of memory!), I suppose you probably could build just about anything on top of it.</div>

<div><br></div><div>But realistically, it seems that (at a minimum) we need to add a way to iterate over ranges of keys and something with multiple storage areas (as you suggested).  Honestly, I can&#39;t think of anything else that seems super important right now.  (Though I know the gmail guys would say they need full text search.  :-)</div>

<div><br></div><div>If it&#39;d be helpful, I could maybe ask some developers here at Google how they&#39;d like to use LocalStorage to get some more concrete use cases.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
There&#39;s several problems with this, such as the names are sort of<br>
crappy, and that getting storage areas an array isn&#39;t very friendly.<br>
However you get the basic idea. </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



We don&#39;t even need to use Storage objects for this. In fact, I hope<br>
mozilla will in a not too distant future come up with an alternative<br>
proposal to the WebDatabase SQL API. Something like this might fit<br>
into such a proposal as I think that&#39;ll have multiple separate storage<br>
areas anyway.<br></blockquote><div><br></div><div>Any chance you could give us a preview of how you envision this API looking?</div></div>