A slight aside but they also provide the ability to apply security updates sanely to all programs using that library on the system (just update the library and restart the programs, as opposed to having to install a rebuilt version of every program that uses the library). Is this a game-changing feature? These days probably not, but it is (again) just needless waste.
And I say this as someone who is currently developing a shared library in Rust that will probably be included in a lot of distributions because I expect quite a fair amount of container runtimes will end up using it. (But I do also work for a Linux distribution.)
Security updates are a plus, but introducing bugs through a shared library is a minus.
I would prefer we focus on robust application sandboxing instead.
At the server datacenter level its pretty much how its handled anyway, you have isolated vm / containers sitting on deduped storage.
... and in my experience, most application developers, and especially the developers who are the most truculently hostile to working with the system versions of libraries and the most likely to demand to bundle in their own copies for "stability" purposes, are really horrible about paying attention to security issues in their third-party dependencies.
When I'm being a user and a sysadmin rather than a developer or a packager, and I have the choice of trusting a developer versus trusting a packager, then, all else being equal, I will tend to trust the packager. Not that I trust either one that much.
Maybe there would be better sharing if I extracted the ELF sections first.
I just ran an experiment on the 20 largest items in my Mac's /usr/local/bin, many of which are Go binaries
for file in `find /usr/local/bin -perm +u+x | xargs ls -SL | head -20`; do split -a4 -b4k $file `basename $file`; done
ls | xargs md5 > md5.txt
cut -d' ' -f4 md5.txt | sort | uniq -c | cut -c1-4 | sort | uniq -c
This gives: (number of 4kb blocks, frequency of sharing) 128021 1
12105 2
13 3
1 4
1 1137
so about 10% of blocks are shared... once. And 1 blocks is shared 1137 (all zeroes).To your second point, we still want fast security updates and more secure code even with sandboxing! EG, sandboxing would not help with heartbleed -- critical data leaked.
So if block level dedupe where the norm linkers would optimize for that instead. Coming from the .Net / Node world you don't statically link but you typically don't have shared libs, all the libs are in the same folder as the executable and dedupe works just fine there because you have just a bunch of duplicated files in different directories. Same with containers and Vm's all duplicating a bunch of the same system files. You get isolation and reuse because its done at a lower abstraction.
As far as security, again my point was a trade off, yes you could potentially get security updates faster along with breaking changes faster. If the sandbox apps had a good way to stay up to date, then they can update upstream after being integrated and tested with the app. If you have an app store of some sort it can watch for and notify to the authors of security issues in libs these use and prompt them to upgrade or be taken down.
I know the app store argument probably isn't popular around here but from my experience it is a far more secure solution especially for the non technical user. If something is really so widely used it should be a api provided by the OS, otherwise it should be bundled with the app individually and code sharing is done in source repos / build systems, at least thats my opinion after all these years.
Deduplication of containers is incredibly coarse-grained -- it's done a whole-layer basis which means that an update to any distribution package in a base image (resulting in a new layer hash when you rebuild on top of it) results in zero sharing between containers based on different versions of the base image. I am actually trying to rectify this problem with the whole OCIv2 effort -- but I wouldn't argue that today's containers make this problem non-existent. To be honest I hesitate to call the current model "deduplication" at all (yes, it might technically be deduplicated but it's not doing it to the degree you think it is).
And note that the page cache sharing you get from containers is also on the file level, so it's strictly no better than shared libraries (since the container filesystems contain shared libraries and that's what's being shared through the page cache).
I seem to recall ZFS deduplication needing tons of RAM. Wouldn't the memory deduplication you suggest similarly require even more memory?
I don't know how ZFS works but the dedup I have seen runs in the background consuming minimal resources.
I would think if your mem-mapping a file that has been depdupped then its could just memap the already deduped block and cache in memory and not consume more memory if another file uses the same block and is memmapped but not sure if any OS does that.
The minus you mention is a consequence of "Move break fast things" webshit philosophy that's so pervasive these days.
Depending on undocumented behaviour and not properly documenting behaviour.
Edit: and forgot to mention ignorance towards security updates caused by modern PL package version locking etc..
It is a culture problem and technology can only do so much to fix that.
By these metrics it's by far the largest rust application I've seen thus far. When fully optimized, it's 11MB in size.
> librsvg-2.so (version 2.40.21, C only) - 1408840 bytes
> librsvg-2.so (version 2.49.3, Rust only) - 9899120 bytes
For your application, I imagine most of your application's code size is in your dependencies -- so if each crate was a separate shared library (for instance) then you'd end up reducing the amount of duplicated code if you had 50 applications that all needed to use RustCrypto.In a larger sense, something that sets out to be a "systems programming language" needs to be exactly the sort of thing suitable for a tiny embedded system, even if it isn't running on one, because everything else builds on top of it. The attitude that "we have tons of power, why not waste it" just doesn't fly at the very lowest levels. You can write a desktop application in Python, and it's broadly fine - but try writing an OS kernel!
And for writing kernels the same applies; without the stdlib, it gets a lot smaller very fast. I've done it, so I think I can count myself on having some experience there. The biggest part of my kernel is a 128KB scratch space variable it uses during boot as temporary memory until it has read the memory mappings from the firmware and bootstrapped memory management on a basic level. The remainder of the kernel (minus initramfs) is then about 1MB large, the largest part after the 128KB scratch space using about 96KB.
FWIW, this is does not seem to be empirically true. The savings are possible in theory, but false in practice.
https://drewdevault.com/dynlib.html
The most used largest libraries, like libc and libpthread, would be dynamically linked by Rust anyways.
But the pain point is on laptops like MacBooks which have comically small storage space for their price point. I think the base models have a measly 256GB SSD and charge crazy amounts for upgrades.
Problem is that portable applications are an alien concept to Linux.
Static builds, AppImage, FlatPak, containers, etc would like to have a word with you.