11 comments

[ 3.3 ms ] story [ 37.6 ms ] thread
> However, when decoding, we must handle errors and skip spaces.

This had me scratching my head. Why would a base64 decoder need to skip spaces? But indeed, MDN documents this behavior:

> Note that: The whitespace in the space is ignored.

JS never ceases to surprise. Also, check out that typo :D

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Probably so you can put in line breaks? Seems common in base64 data, such as armored PGP keys or emails attachments. HTML attributes allow line breaks, although I haven’t seen it done for base64 images.
This might be for compatibility with XML Schema base64Binary, which collapses all whitespace (such as line breaks) to single spaces.
https://chromium-review.googlesource.com/c/v8/v8/+/7208125 v8 changed yesterday to avoid the temp buffer which will likely double the base64 decode speed.

Looks like this was brought up there as a result of this article too, which is neat! And helpful since I was just messing with a node script that is heavily decoding base64

I remember in the early days of Phoenix LiveView on an intranet app using http1 I noticed it was faster to base64 encode an image, putting it in an img tag and sending the diff through the Channel websocket than the regular http request through Cowboy.
Huh. How many frames per second could it hit, do you think?
Does anyone know why Firefox/Servo are so slow compared to the rest?
That blog post left me hungry for more. I was expecting Daniel Lemire to provide a SIMD crazy optimized version that shows the default browser implementations are sub-optimal. But it's not in this article. Anyone knows?
> Browsers recently added convenient and safe functions to process base 64 functions Uint8Array.toBase64() and Uint8Array.fromBase64()

Wow, finally! I've had to work around this so many times in the past (btoa/atob do not play nicely with raw binary data - although there are workarounds on the decode path involving generating data URIs)

base64 is embarrassingly parallel. So just pipe it to the GPU:

  precision highp float;
  uniform vec2 size;
  uniform sampler2D src,tab;
  void main(){
    vec4 a=(gl_FragCoord-.5)*3.,i=vec4(0,1,2,0)+a.y*size.x+a.x,y=floor(i/size.x),x=i-y*size.x;
    #define s(n)texture2D(src,vec2(x[n],y[n])/size)[0]
    #define e(n)texture2D(tab,vec2(a[n],0))[0]
    a=vec4(s(0),s(1),s(2),0)*255.*pow(vec4(2),-vec4(2,4,6,0)),a=fract(a).wxyz+floor(a)/64.,gl_FragColor=vec4(e(0),e(1),e(2),e(3));
  }
HN user: Ah yes let me casually scribble down a tweet-sized base64 encoder that runs parallel on GPU.

Bravo, that is a thing of beauty.