[02]systems

Parallelism, memory, and scheduling.

Notes from projects, not a tutorial. Most of the interesting bugs I have hit were concurrency bugs, or memory bugs that only looked like concurrency.
01

Parallel boolean retrieval

BoolIR takes a boolean query, splits the inverted index into shards, and runs one Cilk task per shard. Each task intersects or unions postings lists that are read through mmap. The main thread merges the partial doc-id lists before ranking.

Indexing is a streaming BSBI pass: read a batch of documents, emit term-document pairs, sort, and merge runs. The memory ceiling stays fixed even when the corpus is much larger than RAM.

The reranker is the slow part. Retrieval parallelises well; a BERT pass over the top results does not, and it usually dominates latency. Adding cores barely moves it.

QUERYand / orSHARD 0postings listSHARD 1postings listSHARD 2postings listSHARD 3postings listMERGEthen rankMMAPONE TASK PER SHARDCILK
BoolIR query fan-out. Each shard reads postings through mmap; partial results are merged before the reranker runs.
02

Work stealing, briefly

Go gives each P a local run queue and steals from other Ps when the queue runs dry. The model is simple. Two things break it in practice: goroutines that block while holding a lock, and counters that share a cache line across Ps.

The first looks like a stalled pipeline. The second looks like a benchmark that gets slower when you add cores. Both are easier to find with a profile than by reading the code.

P0emptyP1P2P3victimSTEALLOCAL QUEUES · ONE PER PSTEAL FROM THE BACK
P0 runs dry, then takes work from the back of P3's queue.
03

Pages, latches, snapshots

abdb stores rows in pages and keeps a buffer pool in front of the file system. Reads take a shared page latch; writes take it exclusively. Visibility is decided by per-tuple XMIN/XMAX fields, so readers do not block writers under snapshot isolation.

The bug I kept hitting was not in the visibility check. It was a page latch left held on an error path.

PAGE 7ROW STORAGEtuple 1xmin 05xmax ∞tuple 2xmin 05xmax 18tuple 3xmin 15xmax ∞tuple 4xmin 20xmax ∞PAGE LATCHSHAREDEXCLUSIVEshared: readers scanexclusive: one writerXMIN / XMAXdecides visibility
A reader walks the rows under a shared latch. Writers take it exclusively, and XMIN / XMAX decide what the reader is allowed to see.
04

A debugger is a scheduling problem

Sylvan uses ptrace to stop and resume a tracee. Breakpoints are int3 instructions patched into the text segment. Before single-stepping, the original byte has to go back; after the step, the breakpoint has to be reinserted.

Most of the code is bookkeeping around waitpid and the states the process is allowed to be in.

TRACEE STATERUNNINGwaitpidSIGTRAPsteppatch48 89 e5 cc 48 83int3 = 0xcc
Every stop is a waitpid return. The original byte goes back before a single step, then the breakpoint is reinserted.

toolbox

What I use.

A short list. These are the things I reach for when a project needs to work at the system level.

Languages

  • Go, for services and tests
  • C, for ptrace and small tools
  • C++, for compilers and BoolIR
  • Rust, for abdb
  • x86-64 assembly, for reading compiler output

Systems

  • Linux: mmap, epoll, processes, perf
  • LLVM: IR generation and passes
  • ptrace and GDB internals
  • OpenCilk: parallel loops and task graphs
  • Page caches, buffer pools, latches

Around it

  • Kubernetes, enough to debug deployments
  • Postgres and SQLite, for comparison
  • Git and Make
  • Python, for scripts I will not keep