memory-leaks

Still reachable: lots of words in many pages.
git clone https://git.kevinlegouguec.net/memory-leaks
Log | Files | Refs | README | LICENSE

blog-roll.md (16217B)


      1 This is a list of blog-ish websites where I found insightful stuff
      2 that I would like not to forget.
      3 
      4 # [Bartosz Ciechanowski](https://ciechanow.ski/)
      5 
      6 ## [Alpha Compositing]
      7 
      8 The good, bad and ugly of how we discretize colors, and
      9 color-blending.  With helpful interactive simulations.
     10 
     11 [Alpha Compositing]: https://ciechanow.ski/alpha-compositing/
     12 
     13 # [Evanmiller.org](https://www.evanmiller.org/)
     14 
     15 I mostly only read the articles dealing with programming languages.
     16 The down-to-earth commentary made me feel like the author both
     17 appreciates the thought process that went into the design, and has
     18 enough hindsight to find where that thought process fell short.
     19 
     20 ## [A Taste of Rust]
     21 
     22 An overview of some of the language's features.  Some comments
     23 resonated particularly well with me, e.g. on nested functions:
     24 
     25 > With other languages, I’m never quite sure where to put helper
     26 > functions.  I’m usually wary of factoring code into small,
     27 > “beautiful” functions because I’m afraid they’ll end up under the
     28 > couch cushions, or behind the radiator next to my car keys.  With
     29 > Rust, I can build up a kind of organic tree of function definitions,
     30 > each scoped to the place where they’re actually going to be used,
     31 > and promote them up the tree as they take on the Platonic form of
     32 > Reusable Code.
     33 
     34 [A Taste of Rust]: https://www.evanmiller.org/a-taste-of-rust.html
     35 
     36 # [fasterthanli.me](https://fasterthanli.me/)
     37 
     38 :::: tags
     39 - Rust
     40 - Go
     41 - Language design
     42 ::::
     43 
     44 In-depth explorations of various topics (I mostly read posts covering
     45 programming language mechanics), told in a dialectic and very
     46 entertaining style that sustains interest over their Homeric lengths.
     47 
     48 ## [What's in the box?](https://fasterthanli.me/articles/whats-in-the-box)
     49 
     50 :::: tags
     51 - Rust
     52 - Go
     53 ::::
     54 
     55 > The Rust compiler is trying to help us.  "You can't just return a
     56 > reference to something", it pleads.  "You need to tell me how long
     57 > the thing that's referenced is will live".
     58 
     59 > * How does one return different error types without forcing a heap
     60 >   allocation?
     61 
     62 … preferably without having to maintain an ever-shifting enumeration
     63 of possible error types?
     64 
     65 Spoiler: there's no escaping the `enum`, but at least
     66 [`thiserror`](https://lib.rs/crates/thiserror) lets us focus on *just*
     67 the enumeration, and generates the boilerplate for the `Display` and
     68 `From` traits.
     69 
     70 # [Et tu, Cthulhu](https://hpjansson.org/blag/)
     71 
     72 ## [A hash table re-hash]
     73 
     74 A benchmark of hash tables that manages to succinctly explain common
     75 performance issues and tradeoffs with this data structure, to show
     76 results across a wide range of implementations, and to provide very
     77 understandable interepretations for those results.
     78 
     79 [A hash table re-hash]: https://hpjansson.org/blag/2018/07/24/a-hash-table-re-hash/
     80 
     81 # [Joe Duffy's Blog](http://joeduffyblog.com/)
     82 
     83 ## [The Error Model]
     84 
     85 An in-depth look at what "errors" are in the context of software, how
     86 some languages choose to deal with them, and what model the Midori
     87 team implemented.
     88 
     89 > Our overall solution was to offer a two-pronged error model.  On one
     90 > hand, you had fail-fast – we called it abandonment – for programming
     91 > bugs.  And on the other hand, you had statically checked exceptions
     92 > for recoverable errors.
     93 
     94 Starts by outlining the "performance metrics" for a good error model,
     95 then goes over unsatisfactory models:
     96 
     97 - **Error codes** clutter a function's signature with an extra return
     98   value, and the resulting branches degrade performance; they do not
     99   interrupt execution unless checked manually, thus when bugs finally
    100   show up, it can be hard to track their origin down.
    101     - Though the Midori team did provide their developers with an
    102       escape hatch that lets them ignore return values, their `ignore`
    103       keyword is at least auditable.
    104 
    105 - **Unchecked exceptions** make it hard to reason about a program's
    106   flow.  They persist because in the grand scheme of things, they stay
    107   out of the way When Things Work™.
    108 
    109 - **Exceptions in general** tend to come with some performance baggage
    110   (e.g. symbols for stack traces), and encourage coarse error-handling
    111   (i.e. throwing a `try` blanket spanning several statements instead
    112   of focusing on individual calls).
    113 
    114 All of these models conflate *recoverable errors* (e.g. invalid
    115 program inputs) that the application can act on (by telling users
    116 about their mistakes, assuming a transient environment failure and
    117 re-trying, or ignoring the error) with *bugs*, i.e. unexpected
    118 conditions that, when unhandled, create bogus states and transitions
    119 in the program, and may only have visible impacts further down the
    120 line.
    121 
    122 As these bugs are "unrecoverable", the team chose the
    123 "**abandonment**" strategy (aka "fail-fast") to deal with them.
    124 
    125 > My impression is that, largely because of the continued success of
    126 > monolithic kernels, the world at large hasn’t yet made the leap to
    127 > “operating system as a distributed system” insight.  Once you do,
    128 > however, a lot of design principles become apparent.
    129 
    130 > As with most distributed systems, our architecture assumed process
    131 > failure was inevitable.
    132 
    133 The micro-kernel architecture, where basic kernel features such as
    134 "the scheduler, memory manager, filesystem, networking stack, and even
    135 device drivers" are all run as isolated user-mode processes,
    136 encourages "wholesale abandonment" as an error-handling stragegy,
    137 since the failure remains contained and does not bring down the whole
    138 system.
    139 
    140 They implemented **contracts** using dedicated syntax and made them
    141 part of a function's interface.  Delegating contract-checking to a
    142 library would have buried pre- and post-conditions as regular calls
    143 inside a function's definition, whereas they wanted them to become
    144 part of the function's metadata, where they can be analyzed by
    145 optimizers, IDEs, etc.
    146 
    147 > Contracts begin where the type system leaves off.
    148 
    149 Contract violations trigger (at worst) program abandonment;
    150 **type-system** violations plainly prevent the program from existing.
    151 
    152 Since "90%" of their contracts were either null or range checks, they
    153 found a way to encode nullability and ranges in the type-system,
    154 reducing this:
    155 
    156     public virtual int Read(char[] buffer, int index, int count)
    157         requires buffer != null
    158         requires index >= 0
    159         requires count >= 0
    160         requires buffer.Length - index < count {
    161         ...
    162     }
    163 
    164 To this:
    165 
    166     public virtual int Read(char[] buffer) {
    167         ...
    168     }
    169 
    170 While preserving the same guarantees, checked at compile-time.
    171 
    172 **Nullable** types were designated with `T?`; `T` implicitly converted
    173 to `T?`, but conversion from `T?` to `T` required noisy
    174 (i.e. auditable) operators which would trigger abandonment when
    175 needed.
    176 
    177 *Recoverable errors* were handled with checked exceptions, which were
    178 part of a function's signature. Since most bugs were dealt with
    179 through abandonment, most of their APIs didn't throw.
    180 
    181 To make it easier to reason about control flow, callers had to
    182 explicitly say `try` before calling a function that might throw, which
    183 did what Rust's deprecated `try!()` did: yield the return value on the
    184 happy path, else re-throw.
    185 
    186 Covers performance concerns, composition with concurrency; muddies the
    187 waters somewhat with "aborts" which kind of look like `longjmp`s to
    188 me?  Except it runs the code in `catch` blocks it finds while crawling
    189 back the stack?
    190 
    191 [The Error Model]: http://joeduffyblog.com/2016/02/07/the-error-model/
    192 
    193 # [Julia Evans](https://jvns.ca/)
    194 
    195 Laconically, ["XKCD's Simple Writer"](https://xkcd.com/simplewriter/) for programmers.
    196 
    197 Lures me in with Yotsuba-like "Wonder!" and "PUZZLEMENT", then pulls
    198 `strace`s and `/proc` dumps on me; by the end of the articles, I often
    199 learned about (a) the article's stated topic (b) very useful tools I
    200 might not otherwise reach for, that are actually broadly applicable to
    201 everyday sysadmin life.
    202 
    203 Article structure emphasizes both "the layperson experience" and "the
    204 scientist's survival guide to computers": observations are made,
    205 questions are asked (readers are polled), hypotheses are made,
    206 experiments are conducted; final statements are wrapped in a neat
    207 little bow with authoritative documentation.
    208 
    209 Sample topics:
    210 
    211 - [Git:](https://jvns.ca/categories/git/) it's not just you; Git _does_ take time to grok, what with
    212   the [extensive terminology](https://jvns.ca/blog/2023/11/01/confusing-git-terminology/) it throws at you, its confusing
    213   notion of [branches](https://jvns.ca/blog/2023/11/23/branches-intuition-reality/) (backed [by survey](https://jvns.ca/blog/2024/03/28/git-poll-results/#branches)) and [commits](https://jvns.ca/blog/2024/01/05/do-we-think-of-git-commits-as-diffs--snapshots--or-histories/).
    214 
    215 - [Terminals:](https://jvns.ca/categories/terminal/) tracing [the journey of a keypress](https://jvns.ca/blog/2022/07/20/pseudoterminals/), finding uses
    216   for [job control](https://jvns.ca/blog/2024/07/03/reasons-to-use-job-control/), untangling [CLI app conventions](https://jvns.ca/blog/2024/11/26/terminal-rules/) from the
    217   OS, the shell & the terminal emulator's features, exposing [the
    218   kerfuffle](https://jvns.ca/blog/2025/01/11/getting-a-modern-terminal-setup/) that holds the [modern]{.wow} terminal experience
    219   together.
    220 
    221 - Also, communication & culture: write a [brag document](https://jvns.ca/blog/brag-documents/), help your
    222   manager [help you](https://jvns.ca/blog/things-your-manager-might-not-know/), chill about [opensource](https://jvns.ca/blog/2014/04/26/i-dont-feel-guilty-about-not-contributing-to-open-source/){.wow}.
    223 
    224 Maintains a [TIL](https://jvns.ca/til/).  Writes [zines](https://wizardzines.com/).
    225 
    226 Showed us how funny [statistically generated BS](https://web.archive.org/web/20181228051203/http://www.uliaea.ca/) can be, before the
    227 industry missed the joke and drowned us in slop.
    228 
    229 # [LispCast](https://lispcast.com/category/writing/)
    230 
    231 Eric Normand's musings on programming paradigms and their application,
    232 with a soft spot for functional programming.
    233 
    234 ## [When in doubt, refactor at the bottom]
    235 
    236 Quoting Sandi Metz:
    237 
    238 > Duplication is far cheaper than the wrong abstraction.
    239 
    240 The point being that blindly following the letter of the DRY law can
    241 lead developers to add complexity to extracted functions because "it
    242 almost does what I want; if I could add just one more parameter to
    243 it…".
    244 
    245 Normand and Metz encourage developers to "mechanically" extract small
    246 pieces of logic; even if they are not re-usable, bundling things
    247 together and naming them helps make the potential abstractions more
    248 visible.
    249 
    250 ## [Programming Paradigms and the Procedural Paradox]
    251 
    252 A discussion on our tendency to conflate *paradigms* with their
    253 *features*; for example, when trying to answer "can this language
    254 express that paradigm?", we often reduce the question to "does this
    255 language possess those features?".
    256 
    257 Normand wonders whether we do this because the procedural paradigm's
    258 metaphor (a series of steps that each may contain any number of
    259 sub-tasks) maps so well to its features (sequential statements,
    260 subroutines) that it trained us to mix those up.
    261 
    262 [When in doubt, refactor at the bottom]: https://lispcast.com/refactor-bottom/
    263 [Programming Paradigms and the Procedural Paradox]: https://lispcast.com/procedural-paradox/
    264 
    265 # Motherfucking websites
    266 
    267 :::: tags
    268 - Web design
    269 ::::
    270 
    271 Satirical websites fighting [web bloat] with minimalist designs.
    272 
    273 - <https://motherfuckingwebsite.com/>  
    274   No style at all, content only.
    275 
    276   - <http://bettermotherfuckingwebsite.com/>  
    277     Increased line spacing, bigger text, reduced line length.
    278 
    279     - <https://evenbettermotherfucking.website/>  
    280       Less contrast, better fonts.
    281 
    282       - <https://thebestmotherfuckingwebsite.co/>  
    283         Satire of the satire, to show that it's possible to be fancy
    284         and stay lightweight.
    285 
    286     - <https://thebestmotherfucking.website/>  
    287       Less contrast, better fonts.
    288 
    289     - <https://bestmotherfucking.website/>  
    290       Use fonts the user already have, compress content.
    291 
    292     - <https://perfectmotherfuckingwebsite.com/>  
    293       Think of internationalization.
    294 
    295 [web bloat]: https://idlewords.com/talks/website_obesity.htm
    296 
    297 # [null program](http://nullprogram.com/index/)
    298 
    299 Chris Wellons's in-depth looks into a fairly wide range of programming
    300 techniques and applications.  The articles often come with
    301 illustrative code samples, which are always broken down into
    302 bite-sized chunks that are easy to grok.
    303 
    304 Some recurring topics I enjoy reading about:
    305 
    306 - GNU/Linux plumbing
    307     - [Raw Linux Threads via System Calls]
    308     - [Appending to a File from Multiple Processes]
    309     - [A Magnetized Needle and a Steady Hand]
    310 
    311 - C programming tricks
    312     - [Global State: A Tale of Two Bad C APIs]
    313     - [C Closures as a Library]
    314 
    315 - Software portability
    316     - [How to Write Portable C Without Complicating Your Build]
    317     - [A Tutorial on Portable Makefiles]
    318     - [Test cross-architecture without leaving home]
    319 
    320 - Algorithmics
    321     - [Inspecting C's qsort Through Animation]
    322     - [A Branchless UTF-8 Decoder]
    323     - [Render Multimedia in Pure C]
    324 
    325 - Emacs Lisp plumbing
    326     - [Some Performance Advantages of Lexical Scope]
    327     - [What's in an Emacs Lambda]
    328 
    329 [Raw Linux Threads via System Calls]: https://nullprogram.com/blog/2015/05/15/
    330 [Appending to a File from Multiple Processes]: https://nullprogram.com/blog/2016/08/03/
    331 [A Magnetized Needle and a Steady Hand]: https://nullprogram.com/blog/2016/11/17/
    332 [Global State: A Tale of Two Bad C APIs]: https://nullprogram.com/blog/2014/10/12/
    333 [C Closures as a Library]: https://nullprogram.com/blog/2017/01/08/
    334 [How to Write Portable C Without Complicating Your Build]: https://nullprogram.com/blog/2017/03/30/
    335 [A Tutorial on Portable Makefiles]: https://nullprogram.com/blog/2017/08/20/
    336 [Test cross-architecture without leaving home]: https://nullprogram.com/blog/2021/08/21/
    337 [Inspecting C's qsort Through Animation]: https://nullprogram.com/blog/2016/09/05/
    338 [A Branchless UTF-8 Decoder]: https://nullprogram.com/blog/2017/10/06/
    339 [Render Multimedia in Pure C]: https://nullprogram.com/blog/2017/11/03/
    340 [Some Performance Advantages of Lexical Scope]: https://nullprogram.com/blog/2016/12/22/
    341 [What's in an Emacs Lambda]: https://nullprogram.com/blog/2017/12/14/
    342 
    343 # [Red Hat Developer](https://developers.redhat.com/blog/)
    344 
    345 ## [10 tips for reviewing code you don't like]
    346 
    347 The article could basically be included as-is in a [nonviolent
    348 communication] textbook and renamed "application to code reviews".
    349 
    350 AFAICT the underlying principle to all these tips is: scrub judgmental
    351 statements out of your responses, and state your concerns openly.
    352 Nobody should expect you to hold all the answers; express your
    353 uncertainty, and let the submitter do the work of convincing you
    354 (e.g. checking for performance regressions, splitting patch series).
    355 
    356 [10 tips for reviewing code you don't like]: https://developers.redhat.com/blog/2019/07/08/10-tips-for-reviewing-code-you-dont-like/
    357 [nonviolent communication]: https://en.wikipedia.org/wiki/Nonviolent_Communication
    358 
    359 # [Without boats](https://without.boats/)
    360 
    361 ## [Not Explicit]
    362 
    363 :::: tags
    364 - Rust
    365 - Language design
    366 ::::
    367 
    368 Picking up where Aaron Turon's ["reasoning footprint"] post left off,
    369 and breaking down "explicit" into more precise epithets:
    370 
    371 "Noisy"
    372 :   `try!()` is noisier than `?`, which works in the latter's
    373     favor.
    374 
    375     > Often - especially when forwarding errors, as `?` does - the early
    376     > return is the least important part of the source code to me.
    377 
    378 "Burdensome"
    379 :   aka "syntactic salt"; can be deliberate in order to
    380     discourage.
    381 
    382 "Manual" or "opt-in"
    383 :   e.g. if Rust required an explicit `.drop()` on variables, instead
    384     of systematically freeing them when they go out of scope.  As
    385     things stand, a variable's eventual de-allocation is "explicit",
    386     as in, it follows non-ambiguously from reading the source code;
    387     yet it is also **automatic**.
    388 
    389 "Local"
    390 :   "explicit within some scope".  Method resolution is explicit (as
    391     in, deterministic and unambiguous) but one('s IDE) must jump
    392     around to figure it out.  `?` is local to the very line where the
    393     early return happens.
    394 
    395 [Not Explicit]: https://without.boats/blog/things-explicit-is-not/
    396 ["reasoning footprint"]: https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html