I’m trying something new. I added WordPress tags for higher level categories of content that cut across the typical tags:
- Deep Dive: Longer, more detailed posts that require significant research. Very expensive to produce.
- Tech: Normal technical blog post. More polished than Lab Notes, less researched than Deep Dive.
- Lab Notes: Rough notes, typically technical, usually bullet points about some topic.
- Essay: Nonfiction writing, usually nontechnical.
- Micropost: Tiny, short thought.
I hope that by categorizing things this way and acknowledging that this blog is a collection of different art forms (that appear similar because they’re all writing), I’ll be more comfortable publishing publicly. For a while I was scared to publish because I don’t have as much time for deep dives as before, which is what people seemed to really like, but acknowledging these different categories and specifically calling out a shorter, rougher, less polished piece as such takes the pressure off of publishing it.
Have you every updated your operating system and your computer rebooted multiple times during the process? Why does this happen? Why isn’t one reboot enough?
In general, if you have some running computer system that wants to upgrade itself, it’s easiest to download the new version, exit, and simply restart from scratch.
This is why you usually have to reboot for OS updates to take effect. On a different level, this is also why you usually have to reboot applications for their software updates to be applied.
The alternative to rebooting is hot swapping: the running program dynamically swapping itself out with the new one — while staying running the entire time. This is harder than rebooting and requires the developer to actually write code to implement this. A reboot-based update generally does not require much code beyond downloading the artifact into the place it will be looked for the next time things start.
If you opt for dynamic swapping, you need to make sure that the update applies cleanly and absolutely in memory — such that there are no lingering pieces of state from the old software lurking. You don’t want to be running half old software, half new software. (Or have old data in memory, half new data)
In general, this is not a problem if you reboot. Reboots start from a clean slate, so you can be sure that after reboot, you’re running with 100% the new software, 0% the old.1
These fundamental principles apply to any update on any kind of system: an application, its dependencies, an operating system (including core userspace libraries), or firmware running on a device.
So why would a computer reboot multiple times during an update?
It’s probably because it has updates A, B, and C to make, and they each require a reboot to take effect.
If there are blocking dependencies between then (C requires B first, which requires A first), there’s no way around doing a reboot after applying each.
If there are no dependencies, then it might be technically feasible to try to apply them all at the same time, and have them all apply together on the next reboot. But even so, such mass changes with multiple things updating all at once can be riskier. So it might still be safest to sacrifice update speed and update in a slower, more controlled manner, one update & reboot at a time.
- There is a migration to a newer, fancier update server infrastructure
- Using this new infra requires a newer version of a core library that is in use on the running old system
- One last update is pushed to the old infrastructure which updates the core library. Reboot once.
- Now the system can fetch a new update ZZ that’s sitting in the new infrastructure, using its new library support. Reboot again.
- And then maybe the version ZZ of the software has some init code that downloads a firmware update for hardware component that ZZ needs to run. This update is incompatible with the previous version and is only applied once ZZ is confirmed to be present and working. Download the firmware update and reboot a third time.
One concrete technique I’m aware of that results in multiple boots is a disk image space optimization.
When building a disk image for a device, it’s common to include a data partition for user data which is separate from the system partition. In real use, the data partition will likely be very large, but when initially building a fresh image, the data partition will be all zeros. This is wasteful and makes the disk image occupy must more space than necessary, which slows down file transfers.
An optimization would be to build the disk image with a smaller data partition — just as big as necessary to hold pre-existing files on the partition. Then on the first boot, resize the partition to occupy the full available space. An easy way to apply that change to the system is to then reboot.
* The exception is persistent state. If your system leaves persistent state on disk or elsewhere, you need to be careful that those artifacts are either compatible with the new system, or migrated.
I chose “offlinemark” as a handle for a few reasons:
- I didn’t want to use my real full name as the handle because of privacy and because I don’t consider my last name a 100% stable API. Ideally this username would last a long time.
- I like adjectives as usernames, but also including my first name makes it feel a bit personal.
- It’s highly unique. There’s a strong chance I can always get this username.
- It’s a bit techy, which is on brand.
- Aesthetics. I dislike numbers in usernames. I like the visual appearance of the text (all on one line, no underhanging characters).
- It’s an aspirational reminder. A lot of the best things in life are offline.
- It appeals to my ironic and quirky sense of humor.
I get asked why I’m into C++ and not Rust.
Above all, it’s pragmatic. C++ is simply what’s used for the work I aspire to do, and I don’t have time for both.
Beyond that, I still think there’s at least one reason to learn C++ today: out of respect for where it’s gotten us. A lot of lessons to learn from something that powers the world, flaws and all.
And when you do learn Rust, you’ll understand it better. The C++ context will give you a deeper & more intuitive appreciation for why it’s like it is.
Rust wouldn’t be what it is without C++. 🤝