Author Archives: Mark

About Mark

Ten years into my journey towards becoming a pro systems programmer, sharing what I learn along the way. Also on Twitter: @offlinemark.

If you're reading this, I'd love to meet you. Please email mark@offlinemark.com and introduce yourself!

Reflections on learning to write

For the last three years, I’ve invested into learning to write. The main reason: strong writing skill is generally a shared quality among all the greatest thinkers, leaders and generally wise people of history.

How has it gone?

Really well. It’s paying off in many ways, and I only feel more inspired to keep doing it. I find that it gets more fun then more you do โ€” the more ideas you have and the easier and faster it is to express them.

It’s paid off in my personal life with my offlinemark project. My writing (and general public creative efforts) has reached some unexpected places and put me in touch with some very interesting people. My most prized accomplishment is being cited in the Linux Kernel security mailing list.

It’s paid off in many ways at work. As a software engineer, I do a lot of writing at work, and I pride myself in having great written communication there. I write a lot of documentation, hold it up to a high standard, and people notice. I get points for this because most engineers don’t like writing docs, but I’ve trained myself to enjoy it.

Beyond these, modern life generally involves a good amount of written communication. I’ve found that putting in these reps has simply made this part of life a bit easier.


P.S. Something else I’ve observed is that I find myself having more ideas and being more aware of them. Whether they’re good or insightful is a different matter, but I’d like to believe that over time they’ll get there.

Learning on your own pales compared to spending time with experts

This has become crystal clear to me at my current job. As much as I’ve had success teaching myself things about computers, nothing, nothing, beats spending time with experts and learning from them.

I had never truly experienced this before and was shocked at how much I was able to learn, in such little time โ€” about C++, git, Linux, and more.

It can be a significant price to pay, but nothing beats literally becoming an employee at a company with experts in a field you care about and joining their team. This is ideal from a learning perspective because as a team member, the experts become invested in your growth and are incentivized to transfer knowledge to you. You just need to be ready to receive it.

Once you’ve tasted this, this truth is also bittersweet. You can only work at so many places. If you have many interests, you now have to live with the fact that for most areas, your learning will be stunted relative to what it could be.


My deep gratitude to the experts in my life: STK, DIR, CSK, MKL, RYB, MZA โ€” thank you.

Back to basics: FIFOs (Named Pipes) and simple IPC logging

FIFOS (“First-in-first-out”s aka Named Pipes) are are somewhat obscure part of Unix based operating systems โ€” at least based on my personal experience. I’ve been using Linux for ten years and simply have never needed to interact with them much.

But today, I actually thought of a use for them! If you’ve ever had a program which had human readable output on stdout, diagnostics on stderr, and you wanted to observe the two as separate streams of text, without intermingled output โ€” then FIFOs might be for you. More on that in a bit.

Youtube version of this blog post:

FIFOs 101

As background, FIFOs are one of the simpler IPC (Interprocess Communication) mechanisms. Like normal (un-named) pipes, they are a unidirectional channel for data transmission. Unlike normal pipes, they can be used between processes that don’t have a parent-child relationship. This happens via the filesystem โ€” FIFOs exist as filesystem entities that can be operated on with the typical file API (open, close, read, write), also similar to normal pipes.

The simplest experiment you can try with them is to send data between two processes running cat and echo.

First, create the FIFO:

$ mkfifo my_fifo

Then, start “listening” on the FIFO. It will hang waiting to receive something.

$ cat my_fifo

In a separate terminal, “send a message” to the FIFO:

$ echo hello > my_fifo

This should return immediately, and you should see a message come in on the listening side:

$ cat my_fifo
hello1

FIFO-based logging, v1

Today I was working on a long-running program that produces a lot of human reading terminal output as it runs. There are some warning conditions in the code that I wanted to monitor, but not stop execution for.

I could print to stdout when the warning conditions occurred, but they’d get lost in the sea of terminal output that normally comes from the program. You can also imagine situations where a program is writing structured data to stdout, and you wouldn’t want a stray log text to be interspersed with the output.

The typical solution is to write the logs to stderr, which separates the two data streams, but as an exercise, we can try writing the logs to a FIFO, which can then be monitored by a separate process in another terminal pane. This lets us run our program with its normal output, while also monitoring the warning logs when they come.

In python, it would look like this (assuming the fifo is created manually):

import time

fifo = open('logging_fifo', 'w')

def log(msg):
    fifo.write(msg + '\n')
    fifo.flush()

i = 0
while True:
    print(i)
    i += 1

    if i % 5 == 0:
        log(f'reached a multiple of 5: {i}')

    time.sleep(.1)

In a separate pane, we can monitor for logs with a simple:

$ while true; do cat logging_fifo ; done

In all, it looks like this:

~/c/2/fifoplay โฏ python3 writer.py
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ while true; do cat logging_fifo ; done
reached a multiple of 5: 5
reached a multiple of 5: 10
reached a multiple of 5: 15
reached a multiple of 5: 20
reached a multiple of 5: 25

Note that the listener process must be running or else the writer will block!

FIFO-based logging, v2

An even more elegant and UNIX-y way to do this would be to still write to stderr in our writer application, but use shell redirection to redirect stderr to the fifo.

import time
import sys

i = 0
while True:
    print(i)
    i += 1

    if i % 5 == 0:
        print(f'reached a multiple of 5: {i}', file=sys.stderr)

    time.sleep(.1)

Which you then invoke as:

$ python3 writer2.py 2> logging_fifo

This yields the same result, just is more semantically correct.

Why you feel stupider than ever, despite being smarter than ever

I’m 10 years into my tech career and yet I constantly feel so, so stupid.

It’s entirely self-originating; not because others are mean to me. (Ok maybe partly also because I’m lucky to be around smart people).

Why do I feel this way, despite mountains of evidence to the contrary โ€” that I’m not stupid, and know a thing or two about what I’m talking about? Is my self esteem really that bad?

I think it’s also because I’ve been learning so much. The more I learn, I more I realize I don’t know. And I posit that the weight of a known unknown feels disproportionately bad to the relief of converting it to known known.

So, the equation looks like:

All Knowns = Known Knowns + Known Unknowns

Perception Of Intelligence = Known Knowns / All Knowns

(Smaller = Less Intelligence = More Stupid)

This makes sense to me. I think I accumulate known unknowns at 10x the rate of known knowns โ€” it takes so much more energy to learn something, than to learn merely of the existence of something.

WIP: Asking for help in the age of AI

Before AI, if you asked someone a question that you could have just as well Googled, you might have gotten a link to letmegooglethat.com.

Sometimes this is fair; question askers do have some responsibility to not ask ultra-common questions which are easily answerable on the internet. But if the answer is not so easily found, it’s valid to ask.

AI changes things because it quickly gives answers to nearly any question. So it vastly reduces the number of “valid” opportunities to ask. Almost everything gets reduced to something that could easily be “AI’d”. That’s especially true if community-specific AIs exist (e.g. trained on your codebase and team wiki at work). Follow this far enough and one could imagine a dystopian future where no knowledge transfer happens human-to-human anymore.

What this robotic understanding misses, and a reason I dislike being excessively strict about lmgtfy’ing people, is that asking questions is a great way to build relationships and community. Communities (especially online ones) need activity to survive and good questions are a great source of activity. Questions often also spark valuable conversations adjacent to the original topic, and those would be missed out on if everyone strictly asked only the AI everything that is answerable by the AI.

Ultimately, I view this change as another step down the existing path of information becoming more readily accessible (like the internet before it, and books before that), rather than something fundamentally different from it.

We’ll use it to improve efficiency in the same way using internet search improved efficiency, but I doubt we’ll fully stop asking each other questions. Beyond the practical reasons (interesting adjacent conversations), relationship building via human-to-human knowledge sharing is too innate to our humanity and we’ll notice its absence.

Everyone’s career sounds more impressive than yours

This is something I’ve observed ever since I started working. Everyone else’s job always sounds way more interesting, technical, or impactful than mine.

For example, when I worked at Trail of Bits, I spent years working on a research project for automatically finding crashes in computer programs using a technique called symbolic execution. Sounds hard! Oh, and the technique is designed for programs where you don’t have source code (sounds extra hard!).

In many ways the job was cool, hard, and technical but what was really uninspiring was that 1. the tool wasn’t actually that effective and 2. we didn’t have any users (probably because of #1). As my colleague Yan once joked, it sometimes felt like we were working on a “Fisher-Price Symbolic Executor”. I often felt like an imposter “playing” software engineer/researcher.

When I visited my old colleagues at Drift, who were working on a web product with thousands of users, I felt inferior. It seemed like they were all working on such impactful and real-world problems. Maybe it wasn’t quite as “novel” as what I was doing but it sounded pretty technical and not easy to me!

However, the way they introduced me to other colleagues that didn’t know me was “This is Mark, he’s moved on and now works on the real hard stuff.” I can only speculate that they felt the same thing that I was feeling. From their perspective, I was working on a super hard, technical, sexy research problem โ€” unlike their boring, run of the mill web app.

This has happened more times than I can count in all sorts of settings, especially conferences, where you’re meeting a lot of strangers who all seem to be smarter than you and do very impressive things at highly functional organizations. (Unlike stupid me, doing unimportant stuff at the dysfunctional dumpster fire of a company I work for!)

The point is familiarity breeds contempt. Being so close to your work dulls the good parts and makes the bad parts stand out sharply in relief. Chances are if you joined their team or organization you wouldn’t find it as rosy as you picture it now.

Dimensions of life happiness

On average, what are the primary, minimal set of life dimensions that collectively contribute towards net happiness?

Or put another way, what are the common causes of dissatisfaction with one’s life, due to lack of something?

Here’s what I could come up with:

  • Monetary Wealth
  • Physical Space
  • Fame
  • Power / Leverage
  • Health / Fitness / Beauty
  • Romantic Relationships
  • Family Relationships
  • Friend Relationships
  • Adventure
  • Freedom
  • Personal Fulfillment
  • Skill

Not everyone is expected to want all of these. But, the list should generally represent the primary desires, on average, of people.

For each dimension, there is no fixed amount that qualifies as “enough to happy” โ€” rather, each goes from zero to “however much you desire in your ideal life”. If you have zero dire for fame, and don’t have any fame, then you have fulfilled this dimension. Note that it is possible also to have too much of a dimension (i.e. too much fame).


WIP: I considered “career success” as something, but I left it out. I think it can be covered by others here.

Dimensions of job happiness

I reflected on the qualities of a job that matter to me and here’s what I could come up with:

  • Technical intensity
  • Personal interest in the domain
  • “Sexiness” of the domain / Can laypeople understand it? (Or better yet, find it intriguing?)
  • Deploy at “scale” (leverage/power) (>= 1000 users)
  • Brand recognition & enthusiasm

These build on top of some base requirements of: working with nice & smart people that I enjoy being around, and being a good fit with the overall company future.

Software engineers must learn to write

There is an immense amount of written communication involved in a programming job:

  • Commit messages
  • Bug reports & debugging discussions
  • Design documents
  • User documentation
  • Project documentation, READMEs, internal dev documentation
  • Project announcements
  • Comments & in-code documentation
  • Making complex situations simple for stakeholders
  • Handling support tickets
  • Mailing list discussions

Software engineers must learn to write well in the same way that they should also learn how to stay organized โ€” they avoid doing so to their own detriment.

How I create so much content

Between my two personal projects, I create a lot of content.

offlinemark:

  • Blog – Writing
  • Twitter – Shorter writing, writing meant to be seen more widely
  • Youtube – Educational content, screencasts
  • Podcast – Stories & lessons from my life, more personal

comfort (my music production project):

  • Music
  • Youtube – Educational content, screencasts on music production
  • Twitter
  • Instagram
  • Podcast

I also have a travel blog that I don’t share publicly.

Some of these channels are more active than others, but I have three principles that help me do it all.

1 – Harvest, don’t generate

I try to harvest content from what I experience & learn in my life, rather than sit down, brainstorm, and generate content from nothing.

2 – Respect inspiration

I’m significantly more productive when I’m inspired, so I try to treat moments of inspiration with great respect and get to work when they come. Sometimes this means being awake at 5:18am writing (as I am now).

Rick Rubin talks about this exact concept in “The Creative Act”.

I try to avoid queueing things at all costs; if possible I just sit down and do it now.

3 – Have buckets for everything

Different kinds of ideas naturally have a medium in which they are best expressed. Insights or essays are best expressed in writing. Educational walkthroughs are best done via screencast. Stories are best told via audio.

I try to have “buckets” (media channels) ready to receive ideas in their best form the moment they strike. This helps you harvest as much of your creative potential as possible.

For a long time, I left content on the table by not having a podcast for offlinemark. I regularly had stories I thought of and wanted to share, but simply had no great place for them, so they weren’t shared. Now that I have the podcast, I notice that I fairly regularly have a thought that is suitable for that medium, and can capture it.


Bonus: 4 – Default to public, and iterate

Don’t get tied up polishing content before you publish it. Default to publishing whatever you have, and remember: You can always polish, expand, or re-release content later. Defaulting to in public maximizes the potential for it to be discovered.


Bonus (Dec 2023 ):

5 – Never let an idea slip

If you’re going to create a lot of content, step one is to not needlessly throw away good ideas when you have them. Ensure that you have some system or tools in place for quickly capturing ideas wherever you might have them. I heavily rely on “Hey Siri, remind me…” on my iPhone which lets me quickly record notes to process later. I use Omnifocus as my todo app which integrates with this. Omnifocus and most other todo apps have a “Quick Add” global keyboard shortcut which is useful if you’re already on your computer.

6 – Not all content needs to be long

Not all blog posts or content needs to be long and arduous to write. In fact, it’s better if it’s not.

7 – Minimize friction

My current blogging setup with WordPress feels very friction optimized โ€” I just browse to my blog, click new post, write, and hit publish. No command lines. No writing in a separate app, then copying the post over. In-place construction if you will.

8 – One-shot it

Get in the habit of “one-shotting” content โ€” forcing yourself to “finish” it in some way in the same session of work. It’s incredibly tempting to leave a piece in a half-finished state and say that you’ll come back later. But rarely does that ever happen and adding things to todo-lists/queues adds weight to your life that doesn’t feel good. Plus, forcing yourself to finish is a creative muscle in and of itself that can be exercised and improved at. I’ve noticed improvement with this for me for music making and writing.