There's been a thread about dependencies lately and the challenge of convincing developers to look at the full dependency chain.
I once maintained a C++ binary that included a PostScript interpreter, a JPEG decoder, a JavaScript interpreter, and a number of other utterly irrelevant pieces causing a huge factor increase in the size of the binary.
The culprit: A single logging statement that invoked a general-purpose printer that could print web stuff. Switching to sprintf fixed it.
@robpike I once found an app had added the pyICU(i18n/l10n) package just to convert european-style floats (3,142) to US/UK style (3.142) in a single line in the codebase.
@snakecharmerb @robpike While at [major tech Co], I found someone had pulled in AspectJ to do some complex bytecode-manipulating code injection in just one place in the codebase. In the end, it was functionally equivalent to simply calling a method. No idea how that got past code review.
@snakecharmerb @robpike that's not necessarily a bad thing, depending on context.
There's more to localising a float representation than just s/,/./.
@nikclayton True! But in this case we could be very confident that the solution was somewhat over-engineered.
Got a link to the thread? May have missed it but sounds very interesting
@robpike in the early Google days "all code depends on everything" was encouraged. Which is how our Java webapp server ended up pulling in almost all of Google's C++ code as a shared library. Occasionally causing memory violations in our otherwise pure Java app. It was a 2-3 month project to tease out the dependencies. Ended up being about 50 lines of code. Our Java servers ran in half the RAM and way more reliably afterwards.
@nelson @robpike I don't mean to single out a specific language but all the new ones seem to brag about how fast they compile code, and often at the expense of human-readability.
I don't need fast compiles! I want my compiler to take all the time it needs to understand every one of my inner-most desires. Plus, I have a Bazel-like build system.
What I need is the system to remove dependencies (or at least highlight them.) My current project has 115k units.
@kellegous @robpike it used to be building the Adwords Frontend (a Java webapp) required building most of the world of Google C++ code. Mostly for utility libraries like file systems. I helped push us to a pure-Java codebase without those dependencies in, oh, 2004?
@robpike one of my former colleagues earned the nickname “Alex the Deleter”. We had a client codebase with six (count ‘em!) different cache implementations, including one which we were able to _prove_ had never been used. (It would have crashed instantly.)
One by one, he deleted them, until we were left with the actual use case, which we implemented with 2 lines of config in Ehcache (which was already a legit dependency).
Several thousand LOC deleted, and many dependencies!
Deleting code effectively is a programming superpower. Most programmers look at the block tower of code and are afraid of removing lower blocks and causing the tower to collapse. Coders like Alex carefully remove enough of them that the tower becomes shorter while keeping the tower perfectly stable. Their trick is to grok the code enough to see the "low load-bearing" code blocks but to the rest of us it looks like they are defying some fundamental laws of programming.
@robpike enter libdeps.py (https://github.com/clearlinux/clr-avx-tools/blob/master/libdeps.py ) to chase these:
$ libdeps.py /usr/bin/true
/usr/bin/true pulls in /usr/lib64/libcap.so.2 because of (3) cap_free cap_get_file cap_to_text
/usr/bin/true pulls in /usr/lib64/libgmp.so.10 because of (30) __gmpz_add __gmpz_add_ui __gmpz_clear __gmpz_clears __gmpz_cmp __gmpz_cmp_ui ...
and it even does this somewhat recursively
@robpike then you had to change to snprintf to fix the buffer overrun