Files
pbrinkmeier.de/blog/utf63/index.html
T

75 lines
5.3 KiB
HTML

<!doctype html>
<html>
<head>
<title>UTF-63</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="../../fonts/source-sans-pro.css">
<link rel="stylesheet" href="utf63.css">
</head>
<body>
<article>
<h1>UTF-63</h1>
<address>
<time>July 2026</time>
·
By <a rel="author" href="../..">Paul Brinkmeier</a>
</address>
<p>
UTF-8 is almost everywhere these days.
The web runs on it, most common file formats use it, macOS, Linux and increasingly even Windows systems use it as the default option.
It makes sense: It's quite compact for mostly-ASCII text and therefore most keywords and symbols of text-based file formats and protocols.
</p>
<p>
What if I told you that in this age of memory bandwidth-constrained workloads you are using a wasteful encoding for text storage?
Most text these days is 99% ASCII with a few emoji sprinkled in (source: Made it up).
<!-- Unicode also defines UTF-16 and UTF-32 but they're even worse for this case, see e.g. the <a href="https://utf8everywhere.org/">UTF-8 Everywhere Manifesto</a>. -->
Even if we ignore the costly multibyte emoji encodings, using UTF-8, 1 out of every 8 bits of memory is wasted on the encoding, because 7-bit ASCII characters are encoded using a whole byte, i.e. we have an encoding overhead of roughly 15%.
</p>
<p>
For example, consider the UTF-8 encoding of the string “🙈🙉🙊 encoding” (see <a href="https://utoy.beany.club/text/🙈🙉🙊 encoding" title="also cURLable!">here</a> for codepoints):
</p>
<pre>11110<span class="red2">000</span>10<span class="red2">011111</span>10<span class="red2">011001</span>10<span class="red2">001000</span> <span class="red2">🙈</span>
11110<span class="orange2">000</span>10<span class="orange2">011111</span>10<span class="orange2">011001</span>10<span class="orange2">001001</span> <span class="orange2">🙉</span>
11110<span class="yellow2">000</span>10<span class="yellow2">011111</span>10<span class="yellow2">011001</span>10<span class="yellow2">001010</span> <span class="yellow2">🙊</span>
0<span class="aqua2">0100000</span>0<span class="blue2">1100101</span>0<span class="purple2">1101110</span>0<span class="red2">1100011</span> <span class="aqua2"> </span><span class="blue2">e</span><span class="purple2">n</span><span class="red2">c</span>
0<span class="orange2">1101111</span>0<span class="yellow2">1100100</span>0<span class="aqua2">1101001</span>0<span class="blue2">1101110</span> <span class="orange2">o</span><span class="yellow2">d</span><span class="aqua2">i</span><span class="blue2">n</span>
0<span class="purple2">1100111</span> <span class="purple2">g</span></pre>
<p>
Colored spans show which code points are encoded by which bits.
Neutral (white on black) bits are encoding overhead required by UTF-8.
For emoji, the most important medium of modern communication, this encoding is obviously horrible.
Every monkey requires a full 32 bits to encode its 21 bits.
And even for good old reliable ASCII, useless bits are sprinkled here and there.
There's gotta be a better way!
</p>
<h2>UTF-63</h2>
<p>
Enter: An entirely new way to encode Unicode!
</p>
<pre>1<span class="red2">000011111011001001000</span><span class="orange2">0000111110</span> <span class="red2">🙈</span><span class="orange2">🙉</span>
<span class="orange2">11001001001</span><span class="yellow2">000011111011001001010</span> <span class="yellow2">🙊</span>
0<span class="aqua2">0100000</span><span class="blue2">1100101</span><span class="purple2">1101110</span><span class="red2">1100011</span><span class="orange2">110</span> <span class="aqua2"> </span><span class="blue2">e</span><span class="purple2">n</span><span class="red2">c</span><span class="orange2">o</span>
<span class="orange2">1111</span><span class="yellow2">1100100</span><span class="aqua2">1101001</span><span class="blue2">1101110</span><span class="purple2">1100111</span> <span class="yellow2">d</span><span class="aqua2">i</span><span class="blue2">n</span><span class="purple2">g</span></pre>
<p>
For our entirely random example, this UTF-63 encoding uses only 16 bytes, a clear win over the whopping 21 bytes required by UTF-8 (that's 30% more!).
So how does it work?
</p>
<p>
Decoding is dead simple:
We consider each set of 8 bytes a Big Endian 64-bit code unit.
If the most significant bit is 0, the other 63 bits contain nine Basic Latin characters (i.e. ASCII characters) at 7 bits each.
If it's 1, they contain any three Unicode code points at 21 bits each (the maximum codepoint is U+10FFFF).
When any of the encoded code points is U+0000 NULL, the string ends there (yes, we're bringing null-terminated strings back. So. many. applications. don't allow NULL anyways).
</p>
<h2>Usage</h2>
<p>
Admittedly, this page actually still uses UTF-8, simply because most modern browsers don't support UTF-63 yet.
To my knowledge, most OSes, desktop applications and programming languages don't either.
It wouldn't surprise me if VLC supported UTF-63 subtitles or something though.
You can do your part by spreading the word among friends, family, flatmates, coworkers and anybody in between.
</p>
</article>
</body>
</html>