>>> import random,zlib,codecs
>>> sample = random.getrandbits(1024).to_bytes(1024, 'big') * 1024
>>> len(zlib.compress(codecs.encode(sample, 'base64')))
22083
>>> len(zlib.compress(codecs.encode(sample, 'hex')))
4326
>>>
edit: (25 minutes of digging around the Internet, and I find this): >>> sample = os.urandom(1024) * 1024
>>> len(sample.encode('base64'))
1416501
>>> len(sample.encode('hex'))
2097152
>>> len(sample.encode('ascii85'))
1310720
>>> len(zlib.compress(sample.encode('base64')))
82169
>>> len(zlib.compress(sample.encode('hex')))
12537
>>> len(zlib.compress(sample.encode('ascii85')))
8212
Had to use Python 2.x to make use of the 'hackercodecs' package that implements ascii85, but looks like it's the best of both worlds, assuming its character set suits whatever medium you are transferring over, and decoding it on the other end doesn't require some slow code.final edit: I'm guessing it was an accidental trick of the repetitive input data lining up well. On real data hex still wins out (which should have been obvious in hindsight):
>>> sample = ''.join(sorted(open('/usr/share/dict/words').readlines()))
>>> len(zlib.compress(sample.encode('ascii85')))
1320809
>>> len(zlib.compress(sample.encode('base64')))
1116678
>>> len(zlib.compress(sample.encode('hex')))
880651symbol_1, symbol_2, symbol_3, ptr_to_1, ptr_to_2,...
ascii85 performs better than hex simply because it's dictionary is shorter.
If you compress something with a bit more structure, like "Hamlet", you'll get this:
>>> import urllib.request,zlib,codecs,base64
>>> hamlet = urllib.request.urlopen("http://www.gutenberg.org/cache/epub/2265/pg2265.txt").read()
>>> len(codecs.encode(hamlet, 'base64'))
248577
>>> len(codecs.encode(hamlet, 'hex'))
368018
>>> len(base64.a85encode(hamlet))
230012
>>> len(zlib.compress(codecs.encode(hamlet, 'base64')))
102788
>>> len(zlib.compress(codecs.encode(hamlet, 'hex')))
88827
>>> len(zlib.compress(base64.a85encode(hamlet)))
121364 >>> import base64
>>> base64.a85encode(b'spam')
b'F)YQ)'
https://docs.python.org/3/library/base64.html#base64.a85enco... $ dd if=/dev/urandom bs=512 count=2048 | base64 | gzip | wc
...
4088 31928 1059085
$ dd if=/dev/urandom bs=512 count=2048 | xxd -p | gzip | wc ...
5019 33798 1231268
1 megabyte of random data consistently results in ~1 megabyte of compressed base64 text, ~1.2 megabytes of compressed hex. $ pv lock-your-screen.png | base64 | gzip | wc
2.1MiB 0:00:00 [ 13MiB/s] [================================>] 100%
8641 48904 2264151
$ pv lock-your-screen.png | xxd -p | gzip | wc
2.1MiB 0:00:00 [4.41MiB/s] [================================>] 100%
10109 49956 2573293
See the same against the jpg version (I've no idea why I have kept both a jpg and png of the same image around, especially given jpg is much better suited format): $ pv lock-your-screen.jpg | base64 | gzip | wc
377KiB 0:00:00 [19.2MiB/s] [================================>] 100%
1420 8373 392796
$ pv lock-your-screen.jpg | xxd -p | gzip | wc
377KiB 0:00:00 [9.36MiB/s] [================================>] 100%
1487 8935 441077
In both cases base64 is both faster and compresses smaller.You only see some compression because gzip is just backing out some of the redundancy added by the hex or base64 encoding, and the way the huffman coding works favors base64 slightly.
Try with uncompressed data and you'll get a different result.
Your speed comparison seems disingenuous: you are benchmarking "xxd", a generalized hex dump tool, against base64, a dedicated base-64 library. I wouldn't expect their speeds to have any interesting relationship with best possible speed of a tuned algorithm.
There is little doubt that base-16 encoding is going to be very fast, and trivially vectorizable (in a much simpler way than base-64).
FWIW, PNG and gzip both use the DEFLATE algorithm, so I wouldn't call PNG's compression "better than gzip".
Source: https://en.wikipedia.org/wiki/DEFLATE
> This has led to its widespread use, for example in gzip compressed files, PNG image files and the ZIP file format for which Katz originally designed it.
Now at least as good is enough for my point: by compressing a .png file with gzip you aren't going to see additional compression in general. When compressing a base-64 or hex encoding .png file, the additional compression you see is largely only a result of removing the redundancy of the encoding, not any compression of the underlying image.
Of course if mom and pop were using UUCP and an ADM-3A to fetch their mail, they couldn't view the images -- but all the infrastructure that allowed them to read mail at all could be repurposed without change, possibly including their modem (thanks, RS-232, introduced 1960), if they bought a 80386 desktop with a VGA card
These are all interoperability success stories! Meanwhile, I need 19 different IM apps on my phone to talk to 19 different people. That's what happens when you ignore interoperability
IO was not ignored, it was willfully cast aside. That's the world of walled gardens we live in today... federation makes it possible for users to switch outside your walled garden.
As for doing something horribly wrong, I dunno, ensuring literally billions of moms and pops can exchange baby pictures by e-mail, for the first time in human history, and doing so since the time when we were using 33.6kbit modems, that seems like a resounding success.†
† Yes, if e-mail had not paid such close attention to compatibility, and just ripped up every old standard on every chance it got (i.e. pretty much like any technology invented since the commoditization of the web), interoperability would never have happened. Legacy crap is fundamentally a part of that success, and Base64 is fundamentally a part of making those hacks practical for the technology we had at the time††
†† To head off an obvious counterargument: yes, there are contemporary examples of why this strategy is still important (it's, so far, the only one that has ever worked in the decentralized environment of the Internet), and is very likely to come in useful in future, time and time again