Storage in the Browser (LondonJS)

Storage in the Browser (LondonJS)

London Web Performance, 16 May 2012.

Fd1af6cc88403788ae1e5710871bbf62?s=128

Andrew Betts

May 17, 2012
Tweet

Transcript

  1. 2.

    ;

  2. 3.

    elcome back to the eb The FT eb app provides

    a touch optimised user experience ithout native code.
  3. 4.

    hy e need local storage •  Reduce aiting times • 

    Launch hile offline •  Maintain state
  4. 6.

    Cookies Tiny size limit Sent in every request to the

    server Idiots in Brussels really hate them So retro your dad’s probably heard of them Universally supported (almost)
  5. 7.

    IndexedDB / ebSQL ebSQL died the moment it as born

    So slo it’s sometimes faster to query the netork (yes really) Only accessible from JavaScript Indexed/queryable data store in the broser. Marvelous. Reasonably ide support if you use both
  6. 8.

    localStorage Synchronous. JS execution blocks on IO Limited to lookup

    by key Only accessible from JS Simple persistent key/value store Really fast
  7. 9.

    HTML5 application cache tomic, nested, impossible to version effectively, buggy

    JS PI, hard to invalidate, etc etc. (ho long do e have?) Caches HTTP responses, so can serve first page request, before JS PIs are available. Easy to cache binary files
  8. 11.

    •  Load an article page hile offline •  Not in

    broser cache, not in app cache •  pp cache serves fallback
  9. 12.

    •  Fallback page acts as client side front controller • 

    Load main JS, CSS, and HTML from localStorage •  Check for errors, trigger startup. Splash  screen   Basic  CSS   Error  msgs  /  support  info   Boot  code  
  10. 13.

    Splash  screen   Basic  CSS   Error  msgs  /  support

     info   Boot  code   Main  app  code   Main  app  CSS   App  HTML  templates   •  Check cookie for user authentication •  Remove redundant content only needed for boot •  Examine URL, read requested content from ebSQL •  Render page
  11. 14.

    Storing content images •  Can’t use app cache, because it’s

    aful. •  Other storage options don’t offer a URL •  Base-64 encode image data •  Store in localStorage or ebSQL •  Insert into DOM as data: URIs •  30% bloat, but also avoids netork operator recompression
  12. 15.
  13. 16.

    ebSQL () / IndexedDB (i) ppcache localStorage Cookies iOS (5.1)

    : 5MB / 50MB 10MB 5MB 4KB total Up to 50 per domain ndroid (4) ? Unlimited 5MB Safari (5.2) : 5MB / Unlimited Unlimited 5MB Chrome (18) : Unlimited 5MB 5MB IE (10) i: 500MB 50MB 10MB Opera (11) : 5MB / Unlimited 50MB / Unlimited 5MB / Unlimited Firefox (11) i: 50MB / Unlimited Unlimited 10MB Storage limits Two  figures  separated  by  /  indicate  limit  with  and  without  user  consent  prompt,  which  appears  automaBcally  when  you  try  to   store  more  than  the  lower  limit.    The  user  may  not  consent  to  more  than  the  upper  limit.  
  14. 18.

    Let’s talk compression •  JavaScript internally uses UTF-16 for text

    encoding •  Great idea for processing: fast string operations, full support for Unicode BMP •  Terrible idea for storage of English text or base-64 encoded images.
  15. 19.

    To bytes per character •  Provides great compatibility but halves

    precious quota! •  Can make compromises on compatibility to get more storage efficiency 00   48   00   45   00   4C   00   4C   00   4F   00   20   00   57   00   4F   00   52   00   4C   00   44   H   E   L   L   O   W   O   R   L   D  
  16. 20.

    Convert to UTF-8? •  Obvious strategy •  Use Byterray in

    JavaScript to store UTF-8 data •  Convert back to string pretending UTF-8 chars are UTF-16 ones (ssssh) •  Just under 50% compression ratio •  Good: Efficient storage •  Bad: Slo to convert, lots of code
  17. 21.

    UTF-8 hiding inside UTF-16 UTF-­‐8   R   o  

    y   ’   s   Decimal   82   111   121   8217   115   As  binary   01010010   01101111   01111001   11100010  10000000  10011001   01110011   ShiSed   01010010  01101111   01111001  11100010   10000000  10011001   01110011   As  hex   52  6F   79  E2   80  99   73  00   UTF-­‐16   副   秢   肙   猀  
  18. 23.

    Use SCII? •  Replace all non-SCII chars ith HTML entities

    server side •  Read char codes in pairs, construct ne string ith one char bitshifted on top of the other. •  Good: Fast, almost as efficient as UTF-8, code is tiny.
  19. 24.

    SCII in UTF-16 UTF-­‐8   S   i   m

      p   l   e   Decimal   83   105   109   112   108   101   As  binary   01010011   01101001   01101101   01110000   01101100   01100101   ShiSed   01010011  01101001   01101101  01110000   01101100  01100101   As  hex   53  69   6D  70   6C  65   UTF-­‐16   卩   浰   汥  
  20. 25.

    SCII to UTF-16 function  compress(s)  {    var  i,  l,

     out='';    if  (s.length  %  2  !==  0)  s  +=  '  ';    for  (i  =  0,  l  =  s.length;  i  <  l;  i+=2)  {      out  +=  String.fromCharCode((s.charCodeAt(i)*256)  +                s.charCodeAt(i+1));    }    return  out;   }  
  21. 26.

    Bit-shifting base-64 data? •  Could go further if e kno

    e’re only using base 64. •  64 characters requires only six bits •  Potential 63% compression ratio •  6 divides into 48 •  8 base-64 chars per 3 UTF-16 chars
  22. 27.

    Base64 in UTF-16 Original   A   B   C

      D   o   p   q   9   b64  index   0   1   2   3   40   41   42   61   As  binary   000000   000001   000010   000011   101000   101001   101010   111101   ShiSed   00000000  00010000   10000011  10100010   10011010  10111101   As  hex   00  10   83  A2   9A  BD   UTF-­‐16   ☐   莢   丢  
  23. 28.

    Base64 to UTF-16 function  compress(s)  {    var  i,  l,

     out='',  map={A:0,  B:1,  C:2,  ...  "+":62,  "/":63};    var  bits  =  16,  chr  =  0,  rem  =  0;    for  (i  =  0,  l  =  s.length;  i  <  l;  i++)  {      if  (bits  >  6)  {        bits  -­‐=  6;  chr  +=  map[i]  <<  bits;        }  else  {        rem  =  6  -­‐  bits;        chr  +=  map[i]  >>  rem;        out  +=  String.fromCharCode(chr);        chr  =  (map[i]  %  rem)  <<  (16-­‐rem);        bits  =  16  –  rem;      }    }    return  out;   }  
  24. 29.

    Summary •  Client side storage is essential part of ne

    generation eb apps •  Currently hampered by fragmented implementation and tiny quota limits •  ith effort, can be used to great effect