168 karma · joined March 29, 2012
These things do way way more than just appetite and craving suppression.
I'm sure some people are going into this without that knowledge, but people are being told this is a lifetime commitment. What you don't see a lot of is why people stop taking it. There's some cases of people losing and then stopping, but the majority are because insurance is forcing people off of it. Just look at the recent CVS Caremark forced switch from Zepbound (2nd Gen) to Wegovy (1st Gen) in July.
Part of the issue I have with the dependency bloat is how much effort we currently go through to download, distribute, compile, lint, typecheck, whatever 1000s of lines of code we don't want or need. I want software that allows me to build exactly as much as I need and never have to touch the things I don't want.
Things like --gc-sections feels like a band-aid, a very practical and useful band-aid, but a band-aid none the less. You're building a bunch of things you don't need, then selectively throwing away parts (or selectively keeping parts).
IMO it all boils down to the granularity. The granularity of text source files, the granularity of units of distribution for libraries. It all contributes to a problem of large unwieldy dependency growth.
I don't have any great solutions here, its just observations of the general problem from the horrifying things that happen when dependencies grow uncontrolled.
For example, you can't split up a module into foo.rs containing `Foo` and bar.rs containing `Bar`, both in module 'mymod' in such a way that you can `use mymod::Bar and foo.rs is never built/linked.
My point is the granularity of the package/mod encourages course-grained deps, which I argue is a problem.
The analogy I use is cooking a huge dinner, then throwing out everything but the one side dish you wanted. If you want just the side-dish you should be able to cook just the side-dish.
This is partly due to how we've distributed software over the last 40 years. In the 80s the idea of a library of functionality was something you paid for, and painstakingly included parts of into your size constrained environment (fit it on a floppy). You probably picked apart that library and pulled the bits you needed, integrating them into your builds to be as small as possible.
Today we pile libraries on top of libraries on top of libraries. Its super easy to say `import foolib`, then call `foolib.do_thing()` and just start running. Who knows or cares what all 'foolib' contains.
At each level a caller might need 5% of the functionality of any given dependency. The deeper the dependency tree gets the more waste piles on. Eventually you end up in a world where your simple binary is 500 MiB of code you never actually call, but all you did was take that one dependency to format a number.
In some cases the languages make this worse. Go and Rust, for example, encourage everything for a single package/mod to go in the same file. Adding optional functionality can get ugly when it would require creating new modules, but if you only want to use a tiny part of the module, what do you do?
The only real solution I can think of to deal with this long term is ultra-fine-grained symbols and dependencies. Every function, type, and other top-level language construct needs to declare the set of things it needs to run (other functions, symbols, types, etc). When you depend on that one symbol it can construct, on demand, the exact graph of symbols it needs and dump the rest for any given library. You end up with the minimal set of code for the functionality you need.
Its a terrible idea and I'd hate it, but how else do you address the current setup of effectively building the whole universe of code branching from your dependencies and then dragging it around like a boat anchor of dead code.
I've now had it happen twice that a car will fully blow through an intersection because they know a Waymo will slam on the breaks to avoid a collision. They basically abuse the car's reflexes.
Also in any sort of situation where the Waymo is being very cautious the biggest danger is the impatient people behind the Waymo who will break the law to go out and around it.
Today those numbers are $11.5k tuition and ~21.5k non-tuition (https://www.calpoly.edu/financial-aid/costs-and-affordabilit...) which is triple the inflation adjusted value from 1997. After 4 years (5 more likely) you're looking at > $125k in costs, which absolutely puts most people into massive loan debt. Even a part time job ($16/h) would offset barely a third of this.
CSU is just beyond expensive compared to 20 years ago.
This is true and "too cumbersome" is worth expanding on. Without specific targeting what is delivered to the device, 100s of MB of storage can be wasted after the APK is uncompressed. The data that is unused can't be deleted but is unusable or unneeded on that device.
When specifically targeting a single device you have multiple axes to target:
* 4 native CPU architectures: [x86, x86_64, armeabi-v7a, arm64-v8a]
* resource DPIs: [ldpi, mdpi, hdpi, xhdpi, xxhdpi]
* 6+ SDK targetSdks with meaningful feature variances (basically potential features enabled/disable every year for the last 7-8 years).
* 80+ individual languages
If the goal is to exactly match the device/user in question, you'd need to generate and apply appropriate versionCodes for: 4 * 7 * 6 * 80 = 13440 individually, versioned, signed and uploaded APKs.
Of additional note, the versionCodes must be precisely ordered to ensure the right version is selected. A device will get the highest version which is compatible with the device. So if an x86 version is higher than x86_64 a 64 bit device that can handle both will still get the x86 instead of the x86_64 version. Same goes for DPI ordering and SDK ordering.
If you have any contact method for the user (email, SMS, phone) you should be doing some level of verification on it. Users are clumsy, some of them don't know or mistype their own email addresses, phone numbers, etc. Verification ensures you're talking to the person you expect to be talking to.
How many of these were real losses and how many were people who put the wrong email address in the box, only to realize when they didn't get the verification email?
I have a very early gmail address, first initial + last, name. I can't tell you how many verification emails I get that I never signed up for. Those aren't the bad ones though, the bad ones are when I get emails about Kay's upcoming surgery and follow-up appointments, Kim's yarn orders and Ken's mortgage documents. (All of these are real examples).
Strong email verification flows aren't just anti-bot. They're a level of defense against clumsy users.
I'm perfectly happy to pay more than most to support others, because I make more than most in income. I can't honestly say that in my day-to-day life I work harder than the person delivering the mail, or someone unloading crates. I was given the advantage of good and cheap education and a safe environment to grow up in (Marin) due in part to high taxes on the wealthy. I feel it's important to do what I can to return the favor.
I also strongly believe that those above a certain threshold of wealth, especially those who hoard that wealth, are doing damage to the economy through income inequality. If taxes are the means to undo some of that damage then again, I'm happy to contribute.
vmnix was the name of the Linux kernel module that was loaded during the Service Console's boot process.
The terms "Service Console", "Console OS (COS)" were at times used interchangeably and referred to the Redhat distro you logged into at the terminal.
VSphere 4.0 had 2 versions: ESX (with COS) and ESXi (without COS). In 5.0 the COS was removed entirely.
Basically the old 1.0 - 4.0 process for _ESX_ was like this:
* Bootloader
* Linux Kernel boot
* Load VMnix module.
* Load VMkernel
* hardware control passed to VMkernel
* Linux continues running as a sort of 'super' VM with some limited hardware access.
For _ESXi_ from 4.0 - now :
* Bootloader
* VMkernel