Compile Your Life.
Published 28 July 2024 at Yours, Kewbish. 3,263 words. Subscribe via RSS.
When I was interning at Cloudflare, my manager taught me about the concept of a “WIP cloud” and drilled it into the team. A WIP cloud is all the dangling PRs, unfinished work, loose threads that you have in flight at once, and it’s dangerous if you let it grow. A WIP cloud starts out fairly easy to manage: you’re wrapping up a PR or have just put something up for review, and now find yourself blocked on others with some spare time on your hands. Being an eager engineer, you look for something else to work on, or perhaps start iterating on the next PR in your stack. Then, you wrap that up — maybe your original PR is still waiting for review — and poke around for some other paper cut to solve. Over time, you amass more and more stuff to just keep on your radar for later.
And then all your PRs get returned at the same time, or all your JIRAs switch from ‘Waiting for response’ to ‘Awaiting team response’. The WIP cloud grows too heavy and starts to pour. You’re suddenly swamped. Now all of those little odds and ends that were easy to keep track of require attention all at once, and while already under pressure, you need to figure out how to prioritize and action on them.
I find myself feeling overwhelmed when I have a WIP cloud brewing, particularly during busy weeks at school or when I have soft deadlines approaching at work. The commonly-cited Miller’s Law states that we can only keep seven items in working memory. After that, we need to rely on context clues to recall things — it’s like paging from disk when the values can’t be found in the cache. When I hit those WIP cloud limits and memory cache misses, I can tell I don’t do very well figuring out what to tackle on the fly.
I’m the type of person that says yes to too much and expects a lot of herself, so in some respects I’ve come to anticipate the WIP cloud before the storm. I try to keep WIP in mind when I go about my work, but avoiding it isn’t the most important. It’s what I do to process the WIP, plan it out, and reduce mental load of having to swap things in and out of my working bubble that matters to me.
I’ve found something that works well for me: a cycle of collection, curation, and execution that I do ahead of time so I can focus in the moment when the WIP storm’s passing by. The metaphor I use for it is compilation — just like compilers, put in some work before the action so you can optimize and take away some computational load while running.
For example, something many “how to become a morning person” articles mention is laying your clothes out the night before, so you don’t have to think about it in the morning, when you’re groggier and vulnerable to taking any excuse to stay in bed. This lets you take advantage of your current, more aware, state, and gives you more time to spot imperfections with your outfit (it’s a very me thing to do, but maybe it’s not a good idea to wear dress pants for a picnic after all).
Compiling your life introduces a split between a more deliberate preparation phase and an execution phase that’s ideally as frictionless as possible. This is adjacent to the divide between System 1 and 2 thinking popularized by Daniel Kahneman’s Thinking, Fast and Slow. System 1 is a faster, snap-judgement mode of thinking, whereas System 2 is slower and requires more mental calculation. We don’t want the execution of our work to be done in System 1, per se — it’s still important work and we need to be deeply focused for it too. But we want to remove all barriers to starting that work, so we don’t want to be forced to plan what work we’ll do as we’re doing it to mitigate procrastination and bikeshedding. We want to be able to access what we’ll do in System 1 mode, so we can spend our System 2 energy on building, creating, and achieving.
If you’re like me, I think you should compile your life too; at least, the times of high pressure and stakes. Make use of more self aware states to make sure even your future unmotivated, frazzled self knows what to turn to. Taking time to do all the logistics, prioritization, and prework first makes the actual work much easier. I’ve used these strategies to make it through six finals seasons and three internships so far. While I think it’s a bad idea to minutely preplan downtime like this, I’ve found it easier to decompress and step away from my responsibilities if I know I can rely on having precompiled what I need to do when I do return.
This post will walk you through how I compile parts of my life, spin off into some loosely adjacent metaphors on compilation, and give you a better sense of how I’ve applied my strategies from hell weeks to hijack my habits.
Get in Loser, We’re Going Planning
The first pass of compilation is planning — collecting and curating whatever you’ll be working on. I first started doing my planning in batches in advance when it came to my first finals season. It’s too easy to realize it’s the last week of class and your first finals are in a few days. When you’re in that high-stress mindset and feeling like you have too many chapters to review and practice problems to work through, the last thing you want to do is spend more valuable time figuring out what to study when. But that’s exactly what I think led to my success in my first few years: I made sure to carve out just an hour or so to figure out a game plan, try my best to cover everything optimally, then forget about editing it and start to focus.
- I make a Google Tasks list each time I have a lot of work to organize. Google Tasks is rather slow and frustrating, but it’s easy to drag around tasks on the calendar, which makes reorganizing work quickly easier.
- I go through and dump out all the chapters, exercises, review sessions, flashcards, or other things I need to do. This is the collection part of planning. See below for how I do this for each class.
- I go in order of the closest exam or whatever I’m most worried about, and space out each task to load balance across the time I have left.
- I go to the next group of tasks, and repeat the same spreading out of work.
- I go over everything and make sure no one day is too heavy. I also edit in some buffer time at this point if I have free days, and a few smaller time blocks to reassess how things are going and adjust my plan if need be.
- I now have a plan of everything I need to do on that day. I’ll sometimes copy over tasks into Calcurse so I can time block and plan on the per-day level.
- Then, when I have a study session or wake up for the day, I just reference my list and get to work. I don’t doom about having so much to do, and I trust in my past self to have allocated time properly.
- Sometimes, things come up, and I need to reorder work or add more. I block out more explicit planning time, drag things around, then go back into execution mode where I don’t think about the what, just the how.
The way I dump out my tasks is also somewhat meta-compiled. I have this template for each course of what I need to reference for each chapter or unit. It might be something like the exercises in the workbook, the review questions at the end of each chapter, and listening and speaking exercises from Canvas, for my French class, and the slides, the PrairieLearn questions, the textbook exercises, the clickers, and my flashcards, for my operating systems class. Then, for each unit, I might have specific areas I want to focus on, so I’ll allocate more time and exercises from those sections. This is a little like monomorphization, a Rust compiler construct for creating explicit instances of generic functions for each type that they’re called with. Here, I’m creating explicit tasks from the coursework templates for each of the units I have to work through1.
I also take time to prioritize during this organization phase: the curation part of planning. Part of making it through the WIP cloud is knowing that to cut or delay (delegation isn’t usually an option for students). When things are laid out across my week in Google Calendar, I can start to see when certain days are too heavy, and if I can’t move things around, I’ll need to decide what’s most important to focus on. A key part of this strategy, though, is making these decisions once while planning, and perhaps scheduling in explicit touchpoints throughout the few weeks that I’m planning ahead. I try not to touch the prioritization outside of this time so I have one less thing that I can do to procrastinate, but more on this later.
During finals week, I can barely find the motivation to drag myself from bed most mornings (especially during the Fall term when I have to wake up in the gloom and dark), so taking the time to plan in advance is helpful so I can start my day right away and know I can make progress.
From Clothes to Chrome Tabs
The next pass of compilation is what I call the precomputation phase — substituting constants and doing basic computation ahead of time. There are certain algorithm problems where it’s more efficient to batch compute all the results at initialization, cache it somewhere, then access those results at runtime. That’s exactly what this preparation stage is useful for in real life as well.
We’ve all heard trite advice somewhere to lay your clothes out the night before to become a morning person. When you’re tired and grouchy, having already made your decision to lay out your workout clothes and your work fit makes it easier to just get up in the morning and go. That’s the same principle precomputation exploits.
You might have heard of the concept of a “trigger list”, an idea first developed in “Getting Things Done”, or a list of all the things you might need to remember or think about on a recurring basis. For example, it might look something like:
- meals:
- planning
- restaurants for eating out
- outfits
- chores:
- laundry
- cleaning:
- bathroom
This precomputation phase takes this idea one step further. Run through the list of triggers you have based on the plan you have, and set up your environment so that you’ve done as much of The Thing as possible without actually doing it. For example, after deciding on your workout fit, fill your water bottle, roll out your yoga mat, and set out your equipment. Pull up the video you’re planning to follow, pair your headphones, and queue your favourite playlist. By putting in all this prep, you’re priming yourself to get up the next morning and just do the thing. Besides, it’ll be easier than putting everything back away again.
One of my first Python projects was a script that’d open up all the tabs I’d want to check through each morning for notifications, including my email, social media, and messages. I haven’t applied quite the same level of janky automation to my studying, but I follow a similar routine. I wrap up each day by going through my todo list for the next session and opening up the textbooks, practice problems, exams, and study tools that I’ll need. When I open my laptop the next morning, I’m greeted not by a blinking screen inviting me to tab over and scroll through Hacker News for an hour, but by what I need to get done.
For work and personal projects, I do the same — at 5PM, or whenever I’m done for the day with my side project, I take a few minutes to figure out what I’ll get done the next day, then open or bookmark the tabs I’ll need to get started. For work, this tends to be opening up my PRs on GitHub so I can refresh and check their statuses the next morning, or the service deploy page so I can remember to hit the button and kick off some tests. For personal projects, I open up my design files for reference or docs pages for the libraries I’ll be using for my next steps.
This principle is inspired by the mise en place cooking technique, so it’s fitting that I also apply it to my meal prep. I don’t follow recipes usually, so I write up my own list of prep steps and from there, set out all my ingredients and cookware and utensils. The weirdest example of this is probably what I do to set up for breakfast: the night before, I’ll get all my cookware (pan, bowl, etc.) in place so the next morning, I can just turn on the stove and start cooking2. This mise step is a textbook example of precomputation: doing the little things to get your station and environment set up so the actual cooking is much easier, and you’re not scrambling around in your cupboards looking for a whisk while your sauce is scalding.
Collecting as much of the paraphernalia related to your work as possible ahead of time helps you avoid distractions. This is most obvious when it’s applied to studying and work, but even in the kitchen or when I’m doing chores, I find that not only knowing what I have to do, but also that I have everything in the right places to get it done, helps with removing all my mental blocks to getting in the flow.
JIT Compiling and Spontaneity
You might think that this all sounds very rigorous and rigid, and it’s supposed to be. Compiling your life is most effective for heads-down periods of life. There are times (e.g. finals week) where I don’t want to think too hard about what I need to do and just execute. I do build in some escape hatches though: above, I’ve mentioned allowing for checkpoints to rejig my schedule, say, in the middle of the week, if need be.
I also give myself the option to “panic” out and restructure at any time. However, I try to ensure that this decision is intentionally done — like an explicit context switch from my “doing” phase to “planning”. Forcing myself to only do so deliberately avoids situations where I don’t want to actually work, so I make myself feel productive by reorganizing my time blocks, or revenge plan after feeling bad for not getting work done. It’s also worth just recognizing what mode you’re operating in at any time to be more cognizant if you find yourself flipping between modes often in order to better plan around that. This Linear blog post, which inspired this post, also has some advice on planning for unplanned work. It’s focused more on product work, but I think its ideas translate fairly well to areas of personal life.
There are plenty of times when I’m less under pressure and I don’t need so much of a drill-sergeant approach — in fact, I’d say that most of the time putting so much effort into planning isn’t fruitful for me. Planning and precomputation are useful when you have very clear goals for a shorter time horizon, when it’s worth sticking to your metaphorical initially-thought-out guns. On the other hand, they’re also premature optimization for lots of other situations. Your mileage may vary, and you’ll have to define for yourself what sorts of times you need these tools and how far you’ll take them.
For more daily-level plans, I try to use JIT compiling: I figure out what I’ll do for the day the day-of, or at the start of a study session. I set aside some time to go through a less-structured version of what I have to do, including high level things I need to think about, and decide then. I timebox these times though, since I feel like it’s super easy for me to get off track trying to figure out the best way to do something, when I just have to go do it.
This summer, I don’t have as many strict responsibilities, so I’m letting myself be looser with all this. I precompute mostly for menial, repetitive tasks, like cleaning and meal prep, and I’ve been blocking in more time to let things come up.
Conclusion
Program, precompute, perform. This is, so far, my recipe for compiling my life, and this is how I’ve gotten through the last few years of my university and industry career.
I’ve been told this sounds robotic, but I’ve realized it’s just like being your own executive assistant. Executives tell their ABPs the high-level initiatives they want to focus on, the presentations and tasks they have to focus on, and the events they need to attend: all the execution work they need to do. Then the ABPs and EAs go out and do all the legwork, the organization, the prepwork, to make it happen. EAs are a separate person from the executive, which lines up well with my ideas of splitting up planning and prework into a distinct phase before execution. My notion of precomputation isn’t even that novel: sure, maybe the EAs don’t go to the extent of logging onto their exec’s laptop to open up all their tabs for them, but they prepare summaries and readings and generally set up their mental environment. If the high net-worth individuals and successful businesspeople of the world have decided to spend money on outsourcing their planning and precomputing so they can focus on the executing, I think there’s some value in doing the same for ourselves too.
The next time you start feeling overwhelmed, consider compiling parts of your work. Do as much of the pre-work and the hard thinking ahead of time, when you’re in a planning mindset, as possible — as much of it as you can without actually doing it. Make the execution the easy part.
I still remember my manager intoning “Don’t let that WIP cloud grow!” at most team strategy meetings. At my current internship I try to remind myself of that whenever I have a free moment and reflexively think of picking something new up. Sometimes I listen and I don’t go for the shiny new thing, and sometimes I do. But when all the consequences of my pending, in-progress, “waiting on action” work hit at the same time, compiling my life helps me make sense of the chaos. Whenever my WIP storm touches down on my mental ground zero, I trust that I’ve done the work ahead of time to make it through.