src/b64url/README.md
This is a simple NIF that is responsible for quickly encoding and decoding Base64 URL values:
1> Thing = b64url:encode("Hello, CouchDB!").
<<"SGVsbG8sIENvdWNoREIh">>
2> b64url:decode(Thing).
<<"Hello, CouchDB!">>
This implementation is faster than the Erlang version in OTP 26-28,
especially for larger binaries (1000+ bytes). To benchmark clone
erlperf repo and run ./benchmark.sh script. In the future, it's
plausible Erlang OTP's base64 module may become faster than the NIF,
due to improvements in the JIT capabilities but it's not there yet.
./benchmark.sh
[...]
--- bytes: 100 -----
Code || QPS Time Rel
encode_otp_100 1 1613 Ki 620 ns 100%
encode_nif_100 1 1391 Ki 719 ns 86%
Code || QPS Time Rel
decode_nif_100 1 1453 Ki 688 ns 100%
decode_otp_100 1 1395 Ki 716 ns 96%
[...]
--- bytes: 1000 -----
Code || QPS Time Rel
encode_nif_1000 1 369 Ki 2711 ns 100%
encode_otp_1000 1 204 Ki 4904 ns 55%
Code || QPS Time Rel
decode_nif_1000 1 455 Ki 2196 ns 100%
decode_otp_1000 1 178 Ki 5612 ns 39%
[...]
--- bytes: 10000000 -----
Code || QPS Time Rel
encode_nif_10000000 1 45 22388 us 100%
encode_otp_10000000 1 19 51724 us 43%
Code || QPS Time Rel
decode_nif_10000000 1 55 18078 us 100%
decode_otp_10000000 1 17 60020 us 30%
NIF implementations must take care to avoid doing lengthy work in a single invocation. This library will yield back to the Erlang VM as needed when operating on a large string, maintaining a partial result until it can resume operation. The current implementation uses a conservative heuristic that estimates 64 bytes of encoding / decoding to consume 1% of a timeslice, so input strings shorter than ~6k should be encoded / decoded within a single invocation, and the library should not adversely affect the responsiveness of the VM in any way.