Your executable is a SQLite database
171 points by jummo
171 points by jummo
inability to mmap/share pages does seem like a pretty big downside, but this is still very cool
SQLite already interns strings
I’m pretty sure that’s not the case, if you want string interning / string deduplication you have to add it yourself via an intermediate table and an m2o.
You can test it by creating two databases with a single table with a single text column, in one insert a million NULL or empty strings (use generate_series), in the other insert a million instance of some longer value. If sqlite did deduplicate, the two databases would be about the same size. They very much are not: on my machine, running sqlite 3.45, a million empty rows[0] is about 8 million bytes (7.7MiB), with a ~30 bytes payload it’s ~41 (40MiB). The overhead of an integer index would be a million bytes per byte[1] (indeed that’s exactly what happens when inserting an integer other than 0 or 1, the table grows by however many bytes storing that integer requires times a million).
And if you read the “database file format” page there is no type code for an out-of-table string, there are two reserved type codes which “will never appear in a well-formed database file”, there is one type code category for blobs (even >= 12), and one for strings (odd >= 13), everything else is reserved for nulls, integers, and floats.
[0] not actually supported so rows with just one column and a typecode-only value: null, 0, 1, or an empty string, so the "value overhead" beyond the row's own metadata is a single byte
[1] the magnitude of the stored integer changes the amount of data needed to store it (1, 2, 3, 4, 6, or 8 bytes)
The children yearn for proper database and record primitives in their OS instead of having to have it in a library.
I do not consider myself a particular fan of SQLite but I think this is a fantastic application for it.
I'd be really curious to see how performance stacks up to, say, appimage. This is delightfully cursed.
https://github.com/fzakaria/selfdb/blob/main/bench/results.md - some perf is here. appimage should still have an edge here, since it can just mount the image and let the normal elf loader mmap the files
This really makes me appreciate statically linked a.out. Here's the Plan 9 variant, for reference:
typedef struct Exec {
long magic; /* magic number */
long text; /* size of text segment */
long data; /* size of initialized data */
long bss; /* size of uninitialized data */
long syms; /* size of symbol table */
long entry; /* entry point */
long spsz; /* size of pc/sp offset table */
long pcsz; /* size of pc/line number table */
} Exec;
Putting a duplicate of all your dependencies into a database just so you can run the dynamic linker on them is a particularly particularly interesting choice.
This reminded me of original MacOS a bit. Files there have a “data fork” (bag of arbitrary bytes) and a “resource fork”, which is an indexed list of binary blobs, each of which has a type and an ID. The resource fork contains a bunch of stuff like the localizable strings, dialog box layouts, etc., but it also contains the executable code, which is just in resources of type CODE. So if you regard the resource fork as a simple database, it was a primitive form of what this post describes.