Portfolio and Publication Strategy
Fifteen projects produce fifteen repositories. That is a list, not a portfolio.
A portfolio is a small number of artifacts that are independently useful to someone who does not care about your learning journey, plus a narrative that connects them.
Table of Contents
- The Standard
- The Nine Artifact Types
- The Standalone Tools
- Publication Timeline
- How To Write the Posts
- The Comparison Matrices
- The Postmortems
- The Final Paper
- The Narrative
- What Not To Do
- References
The Standard
Every major project produces at least one artifact that remains useful independently of the journey.
The test: could a stranger find this, use it, and benefit — without knowing or caring that it came from a 34-month self-directed program?
| Fails the test | Passes the test |
|---|---|
| "My HNSW implementation" | "A benchmark harness that plots recall/QPS for any index exposing add/search" |
| "My distributed KV store" | "A deterministic, replayable fault injector for Go distributed systems" |
| "My notes on Bloom filters" | "Bloom filter theory vs measurement, with the code, and why 200k probes cannot resolve a 10⁻⁵ rate" |
The left column is a record of learning. The right column is a contribution. They often come from the same work; the difference is whether you extracted and packaged the part that generalises.
The Nine Artifact Types
| # | Artifact | Per project | Notes |
|---|---|---|---|
| 1 | Source repository | all 15 | One command to build, test, and reproduce the headline benchmark |
| 2 | Design document | all 15 | Written before implementation. STORAGE-FORMAT.md, LANGUAGE.md, USER-MODEL.md are the strongest examples |
| 3 | Architecture diagram | all 15 | Accurate, not aspirational. ASCII in the README is fine and ages better than an image |
| 4 | Benchmark report | all 15 | Raw data committed, not just summaries |
| 5 | Research notebook entries | ~80 total | The record of your reasoning improving |
| 6 | Failure analyses | ≥1 per project | Often the most-read thing you write |
| 7 | Technical articles | ~8 over the journey | See the timeline |
| 8 | Comparison matrices | 4 | Cross-project synthesis |
| 9 | Demonstration videos | 3 | P05, P12, P15 |
Plus, once: the final paper, five postmortems, and the narrative.
The Standalone Tools
The highest-value portfolio items in the whole journey, because they are used rather than read. Extract each into its own repository with its own README when the parent project ships.
| Tool | From | Why someone else wants it |
|---|---|---|
| ANN benchmark harness | P02 | Accepts any index with add/search, emits the standard recall/QPS curve, reports distance counts alongside wall clock. The distance-count column is what most harnesses lack |
| Crash-test harness | P03 | Randomised kill -9 at N points with acknowledged-write verification. Reusable against any storage engine |
| Deterministic fault injector | P05 | Drop, delay, duplicate, reorder, partition (including asymmetric), pause, corrupt — with replayable seeded schedules. The replay is the feature |
| Linearizability checker | P05 | Wing–Gong with pruning, over recorded histories |
| Batch-equivalence test harness | P07 | Verifies a streaming job against a batch oracle. Rare and genuinely useful |
| Systolic-array simulator | P14 | Cycle-accurate, reports MAC utilisation, validated against the TPUv1 TOPS derivation. Nothing small and readable exists here |
| Gradient-check harness | P13 | Finite differences against any autodiff implementation, across broadcast shape pairs |
bench.py, metrics.py, roofline.py | this track | Already standalone. Publish as one small library |
The fault injector and the linearizability checker are the two most likely to be used by strangers. Both solve a problem everyone building distributed systems has and few solve well, and both are small enough to read in an afternoon.
Publication Timeline
Publish early and repeatedly, not once at the end. Three reasons: external feedback catches errors while they are still cheap to fix; writing for an audience forces precision the private report does not; and a two-year silence followed by a paper is a worse strategy than eight posts building an audience.
| Week | Artifact | Type | Why then |
|---|---|---|---|
| W20 | "Bytecode is 1.5× slower than a tree-walk (in Python), and why" | Post | Your first counterintuitive measured result. Small, self-contained, verifiable |
| W26 | "What a Transformer costs: FLOPs and memory by sequence length" | Post | The cost model table with your own numbers. Widely useful, rarely written |
| W34 | "The filtered vector search cliff" | Post | P03's E3. Directly useful to anyone running filtered ANN in production — a large audience |
| W43 | "Read, write, space: measuring the LSM trilemma" | Post + tool | P04's E3 crossover figure. The strongest early systems piece |
| W50 | Extract and publish the standalone tools | Tools | After Stage 2, when several exist |
| W67 | "A replayable fault injector, and the bug it found in my Raft" | Post + tool | P05's real bug with its interleaving diagram. This is the post that establishes credibility |
| W83 | Video: "Building a distributed system that survives its own fault injector" | Video | Stage 3 synthesis |
| W99 | "When offline metrics fail to predict online outcomes" | Post | P10's E12. Your professional domain, a widely-argued and rarely-measured question |
| W110 | "What a syscall, a page fault, and a context switch actually cost" | Post | P12's MEASUREMENTS.md. Perennially useful reference material |
| W117 | "Why specialised hardware wins: 1.9 to 1,679 GFLOP/s on one laptop" | Post | P14's measured progression. The most striking single result in the journey |
| W126 | Preprint of the final paper | arXiv | Before the polish; timestamps the work |
| W130 | Paper, demonstration video, and the narrative | All | Completion |
Start with W20 even though it is a small result. The habit of publishing is what matters, and a small correct post is a better first publication than a large one you never finish. The bytecode result is ideal: counterintuitive, fully reproducible in one file, and it teaches something real.
How To Write the Posts
Systems posts that get read share a structure. Use it.
- Lead with the number. Not the context, not the motivation — the surprising measurement, in the first two sentences. "A bytecode VM I wrote is 1.5× slower than the tree-walk interpreter it replaced. Both produce identical results to fifteen significant figures."
- State the setup precisely enough to be attacked. Hardware, versions, workload, command. A post whose setup cannot be criticised cannot be believed.
- Show the mechanism, not just the effect. The distinguishing feature of a good systems post is that it explains why, with a secondary measurement that closes the argument. Recall and latency alone say "it plateaus"; the distance counter says "6.9× fewer operations at 67.5× the cost each, predicting 0.10× and measuring 0.10×".
- Include the code. A single runnable file beats a repository beats a snippet.
- Say what you got wrong. The most-shared systems posts contain a mistake the author found themselves. It is also the most credible thing you can write.
- Name the limits. One paragraph: what this does not show, and where it would not hold.
Length: 1,200–2,500 words. Longer than that and the measurement gets buried; shorter and there is no room for the mechanism.
Where to publish: your own site, with cross-posts wherever your audience is. Own the canonical URL — platforms disappear and a two-year body of work should not depend on one.
The Comparison Matrices
Four cross-project syntheses. These are the artifacts that demonstrate systems thinking rather than component knowledge, and they are what distinguishes this portfolio from fifteen unrelated repos.
1. The amplification matrix (after P04) Every storage decision in P03 and P04 against read, write, and space amplification, with your measured numbers next to the derived ones.
2. The consistency/availability matrix (after P07) Every consistency choice across P03, P05, P07: what it guarantees, what it costs in latency, what it does during a partition, and which of your systems chose it.
3. The "where the time went" matrix (after P14) The synthesis of the whole journey. One table:
| System | Bottleneck | Class | Ratio | Fix | What the fix cost |
|---|---|---|---|---|---|
| P02 ANN | interpreter dispatch per distance | constant factor | 67.5× | compiled inner loop | build complexity |
| P11 VM | host-language dispatch per opcode | constant factor | 1.5× slower | compile the VM | — |
| P13 framework | op dispatch below the crossover size | constant factor | — | fusion, graph mode | correctness surface |
| P14 matmul | operand delivery / cache | data movement | 18.6× | tiling + vectorisation | portability |
| P14 vs BLAS | general-purpose datapath | architecture | 29× | specialised silicon | inflexibility |
| P12 syscall | mode switch | boundary crossing | 410× vs a loop iteration | batching interfaces | API complexity |
The pattern this table makes visible: across six different systems in four languages, the bottleneck was almost never the algorithm. It was operand delivery, dispatch, or a boundary crossing. Writing that sentence with six of your own measurements behind it is the single most valuable page in the portfolio.
4. The evaluation-methods matrix (after P10) Offline replay, simulation, and A/B testing: what each can and cannot establish, what each costs, and where your own three methods disagreed.
The Postmortems
One per stage, five total, written at the stage reviews. Plus one per abandoned project, if any.
Not self-criticism. A technical document:
# Stage N Postmortem
WHAT I SET OUT TO DO
WHAT I ACTUALLY BUILT (with the gap named)
WHAT TOOK LONGER THAN PLANNED (and the estimate error, as a ratio)
THE BUG THAT COST THE MOST (and how I would catch it earlier)
WHAT I PREDICTED WRONG (with the pattern across predictions, if there is one)
WHAT I AVOIDED BECAUSE IT WAS HARD
WHAT I WOULD DO DIFFERENTLY
WHAT I NOW KNOW THAT I DID NOT
The abandoned-project postmortem matters most, and its existence is the difference between a completed learning experience and a wound. Write it the week you stop, not later.
The Final Paper
6,000–10,000 words, following templates/report.md's long form.
Full requirements on P15.
The three sections that decide whether it is credible:
- Threats to validity — written before you are asked. Every measurement that could mislead, every assumption you did not verify, every scale you did not test.
- Limitations — what the work does not show. Specific, not modest-sounding.
- Reproducibility appendix — verified by someone who is not you.
The abstract must contain a number. An abstract without one is a description of activity.
Publish the preprint at W126, before the polish. It timestamps the work, it is free, and the version-of-record can come later. See Research Directions for venue options — and note that for systems work, a well-measured post with reproducible code often reaches more of the relevant audience than a workshop paper.
The Narrative
The last artifact, written at W130. One page — a README for the whole journey — that answers:
- What was the goal? Not "learn systems". The specific capability.
- What did I build? Fifteen systems, one table, one line each.
- What did I learn that I could not have learned by reading? The three or four results that required building. The bytecode sign-flip. The ANN constant-factor decomposition. Bélády's anomaly reproduced. The 29× gap to a matrix coprocessor.
- What was I wrong about? The prediction-accuracy record across ~80 notebook entries is a genuinely unusual thing to be able to report.
- What would I do differently? From the five postmortems.
- What is next? From Research Directions.
This is the page you link to, and the fifteen repositories hang off it. Without it, a reader sees a list of projects and has to construct the story themselves, which they will not do.
What Not To Do
| Anti-pattern | Why |
|---|---|
| Publishing nothing until the end | Two years of silence, no feedback, no error correction while it is cheap |
| Publishing a repo with no README | Nobody will read the code. The README is the artifact for most readers |
| Claiming a number you cannot reproduce | One unreproducible claim discredits every other number you have published |
| Comparing against a straw-man baseline | Reviewers and readers notice immediately, and it is the fastest way to lose credibility |
| Hiding the results where you lost | P02 losing to hnswlib by 20× is interesting and honest. Concealing it is neither |
| Writing for recruiters | Write for an engineer with the same problem. That readership is more useful and more durable |
| A portfolio site before there is work | See Not Yet. Markdown in a repo is sufficient until W20 |
| Fifteen equally-weighted repos | Three excellent artifacts with a narrative beat fifteen undifferentiated ones |
References
- Peyton Jones, S. How to Write a Great Research Paper. Microsoft Research, 2004.
- Zobel, J. Writing for Computer Science, 3rd ed. Springer, 2014.
- Shewchuk, J. R. Three Sins of Authors in Computer Science and Math. 1997.
- Collberg, C., Proebsting, T. A. Repeatability in Computer Systems Research. CACM 59(3), 2016.
- Hoefler, T., Belli, R. Scientific Benchmarking of Parallel Computing Systems. SC 2015.
- Blackburn, S. M. et al. The Truth, The Whole Truth, and Nothing But the Truth. ACM TOPLAS 38(4), 2016.
- Bailey, D. H. Twelve Ways to Fool the Masses When Giving Performance Results on Parallel Computers. Supercomputing Review, 1991. Read it as a list of things not to publish.
- Wilson, G. et al. Best Practices for Scientific Computing. PLoS Biology 12(1), 2014.
- Ousterhout, J. Always Measure One Level Deeper. CACM 61(7), 2018. Why the mechanism matters more than the effect — the basis for point 3.