mitschabaude / fast-base64

Fastest base64 on the web, with Wasm + SIMD
MIT License
49 stars 1 forks source link

is still maintained? #5

Open joakimrapp opened 7 months ago

joakimrapp commented 7 months ago

not sure if you care, but i created a ecma one that is more than twice as fast as yours. similar approach, but reading with 16 bits and writing with 32-bits. with a larger dictionary of course. well, again, if you do not care, i'm sorry for disturbing

joakimrapp commented 7 months ago

function exec( a, b, l ) { let s = 0, t = -4, w = a.setUint32.bind( a ), q; while( ( q = b[ s++ ] ) != 0 ) { w( t += 4, ( m[ q ] << 20 ) | ( m[ b[ s++ ] ] << 8 ) | ( ( q = m[ b[ s++ ] ] ) >> 4 ) ); w( t += 4, ( q << 28 ) | ( m[ b[ s++ ] ] << 16 ) | ( m[ b[ s++ ] ] << 4 ) | ( ( q = m[ b[ s++ ] ] ) >> 8 ) ); w( t += 4, ( q << 24 ) | ( m[ b[ s++ ] ] << 12 ) | m[ b[ s++ ] ] ); } }

main loop

mitschabaude commented 7 months ago

Damn, nice! So you're saying this is twice as fast as the JS version of this one? Very cool

joakimrapp commented 7 months ago

sorry for the delay :) yeah, depending on the size of the data (and i guess the version of node/computer etc) it's even faster then node-internal (seems like it's faster when encoding data originating from a 250mb random buffer and also on a 64kB equally random buffer. sometimes also on 1mb buffers). as you might understand it's not by much :) i can give you the code and you can try for yourself.

const t = new TextEncoder(), e = t.encodeInto.bind( t ), A = Uint8Array, B = Uint16Array, V = DataView;
const p = t.encode( '=' )[ 0 ], M = [ ...t.encode( 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/-_' ) ].map( ( c, i ) => [ c, i < 64 ? i : i - 2 ] );
const m = []; M.forEach( ( [ a, b ] ) => M.forEach( ( [ c, d ] ) => m[ ( c << 8 ) | a ] = ( ( b << 6 ) | d ) ) );

function exec( a, b, l ) { let s = 0, t = -4, w = a.setUint32.bind( a ), q; while( ( q = b[ s++ ] ) != 0 ) {
w( t += 4, ( m[ q ] << 20 ) | ( m[ b[ s++ ] ] << 8 ) | ( ( q = m[ b[ s++ ] ] ) >> 4 ) );
w( t += 4, ( q << 28 ) | ( m[ b[ s++ ] ] << 16 ) | ( m[ b[ s++ ] ] << 4 ) | ( ( q = m[ b[ s++ ] ] ) >> 8 ) );
w( t += 4, ( q << 24 ) | ( m[ b[ s++ ] ] << 12 ) | m[ b[ s++ ] ] );
} }
export function encode( a ) { let b = new A( a.length + 16 ), n = e( a, b ).written, i = b.indexOf( p, -18 ), l = i > 0 ? i : n; a = new V( b.buffer ); exec( a, new B( b.buffer ), l ); return new A( a.buffer, 0, Math.floor( l * 0.75 ) ); }

I'm sure it can be further optimised, haven't really put that much effort in cleaning anything up, just wanted to try reading with 16-bit together with larger dictionary and writing in using 32-bit.