15 ms·
Dynamic linking is in my opinion not that useful anymore in this day and age where the few MB of RAM and disk space you save is not worth the hassle. The amount
by greyw 4y ago
Dynamic linking is in my opinion not that useful anymore in this day and age where the few MB of RAM and disk space you save is not worth the hassle. The amount of dynamic linking issues I encountered on GNU/Linux was insane (fuck libstdc++). Not even glibc manages to keep forward compatibility working (breaking memcpy, breaking DT_HASH, ...)!
It's much better to just statically link your binaries (unfortunately many programs on GNU/Linux do not support this).
Before the security guys come out the woods: No you don't need to rebuilt all programs linked against your dynamic library of choice. Just keep the object files around and relink them against the updated version of the static libraries. If now package manager just allowed differential binary updates (actually why is this trivial optimization not a common thing?) the overhead in terms of download size is not that of a big deal too.
The value you gain is immense: binaries just work (modulo linux ABI issues but they are doing quite a good job at keeping this interface stable)
- taeric 4y agoSecurity updates, though? I mean, you aren't wrong. But there were other advantages to dynamic linking.
- Gigachad 4y agoYou are going to see more security improvement by using Rust than the unlikely but possible chance of having your C library incidentally updated.
- palata 4y agoNot convinced at all. Say a big exploit gets published for a very popular library: you probably want to patch it as fast as possible. Whereas Rust will help you have fewer security issues in your own code, which is likely not as popular as some of your critical deps.
- jessermeyer 4y agoThere is obviously a trade off here, but categorically speaking, new releases introduce new bugs and security exploits too.
- palata 4y agoBut they do patch the known security exploits that are likely to be actively used. I'm happier with a security exploit (almost) nobody knows than with a published one that appears in hacking tutorials from 10 years ago.
- jessermeyer 4y agoThere are two degrees of separation here though: The software vendors and then the linux distros. If you sell software that requires your clients to upgrade their system-wide security stack, so they might not. If it is statically linked, no need for them to.
- pornel 4y agoDynamic linking is not the only way to deliver security fixes, just one particular, limited, C-oriented solution. Note that dynamic linking is also not sufficient to change C++ templates or C header-only libraries. It shifts all of the code replacement complexity from the OS (just replace a file) onto the language and library authors (ABI compat, fragile base classes, no inlining or generics). Rust/Cargo gives you Cargo.lock (and more precise build plans if you want) that can be used to build a database of every binary that needs to be rebuilt to update a certain dependency. Distros could use it identify and update all affected packages. There are also caching solutions to avoid rebuilding everything. It's just something they didn't have to implement before, so naturally distros prefer all new languages to fit the old unbundled-C approach instead.
- DelightOne 4y agoSo.. how do you rebuild apps without having access to their source code?
- pornel 4y agoYou ask the vendor, since they need to look after their software anyway. Don't count on closed-source abandonware to conveniently have all vulnerabilities placed in external libraries.
- DelightOne 4y agoI am talking about apps on the iPhone where Apple does not have access to developers' source code, right? We might be talking about different situations.
- pornel 4y agoUpdates of system libraries there are definitely a plus. However, besides the OS itself Apple doesn't do anything about app security. Not only they don't require unbundling, they don't even support it. Even if you use dynamic libraries in your app, they will be bundled with your app, and never updated separately. From App Store perspective there's absolutely no difference between a Swift app diligently split into frameworks and a Rust monolith library. They treat both as an opaque bundle.
- Jach 4y agoI like SDL2's approach to enable both: https://old.reddit.com/r/linux_gaming/comments/1upn39/sdl2_adds_dynamic_api_magic_to_allow_updating_it/ https://old.reddit.com/r/linux_gaming/comments/1upn39/sdl2_a... A game can statically link the library, but the user can with an environmental variable override the functions to point at their dynamic library instead. Very useful especially with games as you can then keep them running on new platforms or fix certain bugs even though the developers have long since disappeared or moved on.
- palata 4y agoBut then if it works with shared libs, you kind of lose the advantage of the static linking which was mostly (if I understand correctly) that dynamic library was not working well...
- Jach 4y agoIt's up to the user if they want to see whether the dynamic library is "working well". They work well for many people! But the statically linked version will be used unless their custom env variable is declared, everyone can be happy.
- Gigachad 4y agoDynamic linking doesn't even really save disk space https://drewdevault.com/dynlib https://drewdevault.com/dynlib The vast majority of libraries on your system are used by only one program. I'd imagine dynamic linking also freezes progress and improvements on libraries because it's extremely difficult to roll out changes without breaking packages that haven't been tested and updated for them.
- rektide 4y agoWe run hundreds of processes on big nodes at work & we absolutely would save hella hella memory & have way better cache utilization if we could share the massive massive massive reams of code each process duplicates for itself. Static linking is basically like running Electron. You take a wonderful multi-machine capable environment then use it to run a single thing, exacerbating the size of what should be minor overhead. As a Linux user, there's like 30 dependencies used by basically half of what I run. If you click in to the article & look at the first chart, it shows this clearly: it tapers down quickly yes but so what? What actually matters? There are a good solid chunk of core libraries used en volume. You dont save much disk space, yes. But many libraries are used by many-hundreds of consumers. Thats where the pain is, that's the loss, that's where you are burning memory space again and again and again with every process you load, and worse, is the cache you are contesting for no reason. You could share that. You should. Giving it up is only because someone has decided it's too hard & too difficult to try,.. and sometimes they are right. But most Linux distros have been working through & managing it & doing ok for years.
- charcircuit 4y ago>We run hundreds of processes on big nodes at work & we absolutely would save hella hella memory & have way better cache utilization if we could share the massive massive massive reams of code each process duplicates for itself. Assuming those hundreds are mostly duplicates why can't they all share their entire code section?
- rektide 4y agoThere's ~60 different things we run. It would be tempting to try to make some kind of a group scheduler. But on the other hand, we get some nice load levelling/load-averaging from having mixed processes. Ultimately there's not really any reason for us to have static linking, but it's just "how it's done" now and it's unquestioned and there aren't as many well established alternatives as there ought to be.
- malkia 4y agoYou can't ship reasonable plugin for most of the popular content creation tools - be it audio, video effects, 3d modelling, etc. without support for dynamic/shared libs. Okay, maybe you can - at the risk of performance cost - e.g. your out-of process plugin that need to move data in/out with a cost, and then it over complicates - because the plugin process might've died - how do you restart it, how do you get it back to state, etc. etc. You just don't have to solve this with .dll or .so
- greyw 4y agoI'm not saying you need to never use dynamic libraries. Some tools (especially handling/supporting puligins) obviously should make use of dlopen and co. It's just doesn't make sense in my head why e.g. nano dynamically links against 10 libraries. Lots of pain for little gain. Latest dynamic linking bug I just encountered is that big picture mode of steam crashes somewhere in libstdc++ when said library is too new but works fine on older versions.
- deleted 4y ago[deleted]
- pornel 4y agoApart from most perf critical cases, it's a good idea to run plugins in a separate process anyway. This way a bad plugin won't crash or corrupt your own process. You will be able to stop and unload it without risk of leaving locks locked or thread-locals leaking. And also there's WASM now which has even better sandboxing and OS/architecture independence.
- Joker_vD 4y ago> Just keep the object files around and relink them against the updated version of the static libraries You've just describe the gist of dynamic linking, you know that, right?
- greyw 4y agoThe end user gets a single statically linked binary which is what matters. The quoted sentence refers to distro maintainers providing new binaries.
- Joker_vD 4y agoAh, so I (the programmer) build object files, send them to the distro maintainers, they link them with their specific versions of the libraries, ands send the resulting executable binary to me/other users. ...that's remote dynamic linking, only with (potentially) human intervention in the loop. I kinda see how it would have worked better if the distro maintainers cared about package quality and speedy updates but they don't (bacause they physically can't, it's way too much effort for way to few people). Look, I don't argue that dynamic linking has zero problems — heavens know how much I've struggled with glibc but that's mostly because glibc is bloody insane. The whole slew of GNU dynamic-linking-related extensions to ELF is insane, now that I think of it.
- greyw 4y agoThe distro maintainers take your source code and package it. If they need to update the program due to an outdated dependency they don't need to recompile the whole program but rather just relink their cached object files with the newer version of the static library (if applicable).
- Vogtinator 4y agoObject files are compiled code with the API and ABI already baked in. This approach effectively combines the downsides of static and dynamic linking.
- ridiculous_fish 4y agoApple uses dynamic linking to enable its OSes to evolve. Apple's libraries talk to daemons using IPC protocols such as XPC or MIG; if those libraries were statically linked, the daemons would have to support old protocols forever. And when Apple changes the appearance of its UI, they want all apps to get the changes immediately, and not wait for the apps to be recompiled. For example, way back I implemented window resizing from all sides and every app just got it on day 1; no recompilation necessary!
- ip26 4y agoAs a late inductee to their ecosystem, I think this strategy is paying off for them. Not sure if this angle was ever pitched as part of the dynamic/static holy wars, aside from security patches.
- saagarjha 4y agoIt’s the main reason why dynamic linking is popular. It’s just that the people on Hacker News often write client software for Linux rather than having to deal with ABI compatibility :)
- andyonthewings 4y agoIt's a common argument of computers getting powerful so we don't need to care that much for performance and/or efficiency regarding to cpu/memory/storage etc. In some limited cases the argument is valid but most of the time it's not. First of all while maybe desktops and mobile phones are more powerful now, but we're getting more and more lower spec devices, like smart watches. Even when smart watches will be powerful enough one day, there will be eventually smaller computers, like smart contact lens, nano robots that run in blood vessels etc. Secondly efficiency is still favourable for powerful computers. A small percentage of cost reduction can be big money save for large corps. A small percentage of energy save of all (or just a portion of) computers in the world can be a big win for the environment. Lastly, we also run VMs and containers everywhere. Notice how we've already come up with all kind of ways to minimise VMs and containers size and footprint, in order to run more of them, to start them faster, and to transfer images quicker.
- wtetzner 4y agoIt depends on what kind of efficiency you care about more. Static linking can allow optimizations across library boundaries.
- josephg 4y agoYep. For hot call sites, these optimizations & inlining opportunities make a massive difference to performance. Static linking also allows for faster application startup time. (Though I don't have an intuition for exactly how slow dynamic linking is). The only argument for dynamic linking being more efficient is that each dynamic library can be shared between all programs that use it. But not a net win in all cases. When you dynamically link a library, the entire library is loaded into RAM. When you static link, dead code elimination means that only the code you actually run in the library needs to be loaded. But honestly, none of these arguments are strong. Dyld is fast enough on modern computers that we don't notice it. And RAM is cheap enough these days that sharing libraries between applications for efficiency feels a bit pointless. The real arguments are these: - Dynamic linking puts more power in the hands of the distribution (eg Debian) to change the library that a program depends on. This is used for security updates (eg OpenSSL) or for UI changes on Apple platforms. Dynamic linking is also faster than static linking, so compile times are faster for large programs. - Static libraries put power in the hands of the application developer to control exactly how our software runs. VMs and Docker are essentially wildly complicated ways to force static linking, and the fact that they're so popular is evidence of how much this sort of control is important to software engineers. (And of course, statically linked binaries are usually simpler to deploy because static binaries make fewer assumptions about their runtime environment.)
- rektide 4y agoDynamic linking is the shit! It's so undersold. Static linking has been convenient & simple, but it gives up so much awesomeness. On consumer systems, memory pressure is real, and being able to have quarter your program be effectively free is enormously helpful. Cache hits also go way up, which can be even more vital. Server side, it depends. If you just run a db server and a monolith, it indeed doesnt matter. But if I look at the hosts we run at my work, if you look at many clusters, they're big nodes and they're running hundreds of processes. If we could get back decent double digit percent of memory that would be great. If caches would get more effective that'd be super. We're leaving a ton on the table because nothing is shared. There's similar works to win back basic obvious performance happening in a number of places. Composefs has shown up on HN a couple times, trying to let containers effectively share files & page-cache. Will I deny that dynamic linming has brought pain? No. But I think it's important to recognize that this is a fallback position. If we were better about not breaking conpatibility, not introducing changes, this would be less of an issue. If we had better software testing that could help us detect & see incompatibility faults as they arise, if we could canary test a new software Bill-of-Materials & have some early indicators, we might have, a decade ago, not collectively decided to give up & give in to "binaries just work".
- lamontcg 4y agoIf you don't care about saving disk space then just ship all your dynamic libraries with your binaries.
- wongarsu 4y agoThat pretty much sums up what everyone does on Windows. Lots of things are linked dynamically, but apart from the C/C++ runtime library and the OS libraries you just ship all those DLLs with your software. But this works because in Windows each software is installed in it's own folder, and the search path for dynamic linking starts in the binary's folder. That way you can just dump everything in your installation folder without worrying about comparability with other software. In a Unix or Linux this is much harder to achieve. Sure, you can install into your own folder in /opt and add a wrapper script to load libraries from there, but it's hardly idiomatic.
- lamontcg 4y agoI did it for 10+ years at my last job, you need a build system that hammers on everything really hard to set the rpath on everything, you shouldn't need wrappers. It definitely isn't idiomatic though.
- alexvoda 4y agoWhat is the philosophy behind why it's not done like this Linux? Also, what about Nix?
- eschaton 4y agoYou assume there’s a philosophy or coherent reasoning behind it, rather than “This is the way we did it with static libraries, so when we adopted shared/dynamic libraries we didn’t change anything else.” Because near as I can tell that’s exactly what happened when BSD and Linux implemented Sun-style .so support in the early 1990s, and there hasn’t been any attempt to rethink anything since then.
- darknavi 4y agoSteam encourages devs to dynamically link SDL2 so that they can patch it for them [0]. Pretty neat IMO. Sorry for the terrible link, Google+ is deleted now but luckily a bot mirror the post to reddit. [0]: https://www.reddit.com/r/linux_gaming/comments/1upn39/comment/cekfh1u/?utm_source=share&utm_medium=web2x&context=3 https://www.reddit.com/r/linux_gaming/comments/1upn39/commen...
- silon42 4y ago"Platform" libraries, like UI toolkits, ... should always be dynamically linked...
- m4rtink 4y agoThis is also how Linux distro wide CVE fixes in crypto libs are done - done tmit once in the shared lib and reboot, done. Otherwise you would have to find all the bundled copies and fix them separately & hope you didn't miss any.
- pjdesno 4y agoNice. Now you have to convince all your software providers to ship those object files. I'm sure it won't be a problem, it's only a really huge change to the entire way in which software packaging and distribution works today... It's fine as a thought exercise, and might work really well in a restrictive environment (e.g. Google) where you control all the source going into your system. For what most of us call the Real World, it's highly problematic.
- panzi 4y agoRedhat has .drpm, but I'm not sure at what granularity those diffs work. Maybe only on a per-file basis?
- Vogtinator 4y agoIn (open)SUSE we also use delta RPMs. They work in a slightly odd way: The CPIO archive of the installed RPM is is rebuilt based on the installed files, then a binary diff is applied to create the new RPM. That is then installed. (ref: https://github.com/rpm-software-management/deltarpm https://github.com/rpm-software-management/deltarpm) It saves a lot of bandwidth, but takes a huge amount of local resources to install them so I just disable deltas everywhere.
- musicale 4y agoInteresting suggestion - basically treating a statically linked binary as a cache which is invalidated when any of the dependencies is updated, triggering either proactive or reactive relinking. The disadvantage vs. dynamic linking is that you can't easily replace libraries on the fly. It is less flexible but it might actually be better for security. Dynamic linking could be emulated, albeit slowly, by relinking each time a program is launched. This would be slower but potentially useful for certain purposes such as debugging.
- dusted 4y agoI too wonder if it's worth the effort to ship around a trillion versions of different libs (with their trillions of different versions of dependency libs)^n. One neat thing about it is that we get to override functionality easily, either by replacing entire binaries (such as we do with glide-wrappers to get our 3Dfx fix on modern windows machines) or by using LD_PRELOAD to load hooking SOs to fixup data in old binaries as they are used.
- physicsguy 4y agoThe best argument for dynamic linking IMO is not the runtime distribution but the cost of linking everything into a static binary while developing.
- pjmlp 4y agoDynamic linking great for plugins and OS extensions, which otherwise will require tons of processes doing IPC, with serialized data. Great if you have hardware to spare and enjoy Electron like experiences. The only plus side is being safer to the host application.
- inkyoto 4y agoThis is a somewhat myopic take on the value of the dynamic linking. One important aspect is that a dynamic library provides a host of implementations that have been tailored or optimised for specific subsets of CPU's or specific generational CPU features. Let's take «memcpy» as an example that is taken for granted. «memcpy» is defined as weak symbol in the libc.so or similar, and the dynamic linker will replace it with a version that has been optimised for the CPU flavour and CPU flavour's features that have been detected at the runtime or replace it with a less performant, default generic implementation if the dynamic linker does not recognise or support a particular CPU variety. Remember how «memcpy» got an instant manyfold speedup when the AVX-512 optimised version appeared? Yep, all dynamically linked binaries got an instant speedup without even noticing the change. The same will happen (likely, it has already happened) for aarch64 SVE2 vector instructions, and it will happen for RISC-V 64 bit once the vector extension is ratified etc. Doing away with the dynamic linking will slow the adoption of new CPU features down substantially. If you do away with the dynamic linking, you will not be able to troubleshoot or debug a failing app by substituting the default «malloc» with a debug (or a more performant) implementation via LD_PRELOAD. The Boehm garbage collector was widely used this way (whilst it was being maintained) to overload «malloc» and «free» to successfully run leaky apps that would run out of memory without the GC. Then there are linking times. Linking Chrome and KDE binaries has been reported to take over an hour and require vast amounts of disk space. We now have «sold» and «mold» so it might be less of an issue but they are not a mainstream linkers yet. Updating a single dynamic library is undisputably faster than relinking 100k binaries that use it. 99.999% of end users will never bother with the relinking anyway. Naturally, you could claim that the same can be accomplished by fiddling with link maps supplied alongside of object files, but… the link maps are hostile to developers and require a large body of the low-level fringe knowledge that libc authors have taken the burden of. The link maps would have to be very detailed thus very large and also require every developer to have an advanced degree in witchcraft. That would hamper software development efforts for nearly everyone. Which is not to mention that distributing object files has been tried before, and it has never caught on especially amongst commercial vendors for a number of mostly non-technical reasons. The amount of IP that can be extracted from an object file and the ease of extraction has made the vendors unwilling to distribute anything that is not a final binary product and balk at the idea of it. You could make a stronger case with suggestion with the OS/400 style of the static binary translation (or AOT) which is functionally combines benefits of object files and some dynamic library features (with the exception of LD_PRELOAD that would have to be replaced with a separate AOT run to «re-link» the final binary product with whatever version of «malloc» / «memcpy» / etc is required), and LLVM has tried that with Bitcode, but for a reason unclear to me, Bitcode seems to have been fading away.
- mid-kid 4y ago> Just keep the object files around and relink them against the updated version of the static libraries. This wouldn't work, as extra care needs to be taken to not break the ABI of a shared library. We have various conventions to aid with this including but not limited to "so versions", but these must be kept in mind by the library developer. Object file ABI stability isn't even guaranteed by the compiler. Also, these days with LTO, the linking step takes a tremenduous amount of time anyway. Doing this wouldn't help much.
- audunw 4y ago> Dynamic linking is in my opinion not that useful anymore in this day and age where the few MB of RAM and disk space you save is not worth the hassle But space in fast cache IS worth the hassle. It's still extremely limited, and since we're hitting the limits of moore's law we're not getting much more of it. The article touches on this. Statically linking can be a case of "tragedy of the commons" if you statically link a single program, you only see the benefits. But if you statically link all programs in a system, vs dynamic linking of all programs, you're giving up on the chance of having shared caching of commonly used pieces of code between programs, and you're giving up on minimizing code size so you don't have to prematurely evict useful code from the cache. The article touches on this subject: > It’s worth noting that the Swift devs [...] care much more about code sizes (as in the amount of executable code produced). More specifically, they care a lot more about making efficient usage of the cpu’s instruction cache, because they believe it’s better for system-wide power usage. Apple championing this concern makes a lot of sense, given their suite of battery-powered devices.
- julik 4y agoWith a "single vendor" providing your stdlib (Apple is a good case in point) dynamic linking is actually better. It is also absolutely no fun whatsoever to recompile your entire hard drive when doing development (which is what Rust work is mostly like, but also Crystal and other "static link everything" approaches). Static linking for a "fast deployable binary for minimum common denominator OS" like the one Go supports is great, but it is great for a usecase (downloadable binaries with narrow functionality) and when your dependency stack is small (no UI, no accessibility, no graphics, no native code). IMO dynamic linking is rad if you have a known system compatibility table and known vendor (distro) selection for the OS components/key deps. The issue rather is that it is a pain in the butt to configure and understand.