<?xml version="1.0" encoding="utf-8"?>

<feed xmlns="http://www.w3.org/2005/Atom" >
  <generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator>
  <link href="https://numi.st/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://numi.st/" rel="alternate" type="text/html" />
  <updated>2026-03-14T09:25:05+00:00</updated>
  <id>https://numi.st/feed.xml</id>

  
  
  

  
    <title type="html">numist log</title>
  

  
    <subtitle>The public memory bank of Scott Perry.</subtitle>
  

  
    <author>
        <name>Scott Perry</name>
      
      
    </author>
  

  
  
  
  
  
  
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">United we Bargain, Divided we Beg</title>
      <link href="https://numi.st/post/2026/united-we-bargain/" rel="alternate" type="text/html" title="United we Bargain, Divided we Beg" />
      <published>2026-01-23T18:33:28+00:00</published>
      <updated>2026-01-23T19:00:48+00:00</updated>
      <id>https://numi.st/post/2026/united-we-bargain/</id>
      <content type="html" xml:base="https://numi.st/post/2026/united-we-bargain/"><![CDATA[<p>My paternal grandparents, uncles, aunts, sister, and brother-in-law were all union. Strikes—even their threat—are a powerful tool when negotiating with management. I am pro-union, and I support strikers.</p>

<p>Taking a day off work is not a strike.</p>

<p>Power will only recognize threats to power, and strikes threaten a company’s bottom line. If everyone takes a day off work, the effect on production can be completely eliminated by the elasticity of work. This is especially true for exempt<sup id="fnref:hourly" role="doc-noteref"><a href="#fn:hourly" class="footnote" rel="footnote">1</a></sup> employees, who are usually expected to deliver regardless of time off and have been indoctrinated over their careers into making up for “lost time”. In fact, the evolution of the economy during the era of modern trade unions has made strike effectiveness more complicated—a company can weather a strike for longer if it has spread its production out across demographics<sup id="fnref:locations" role="doc-noteref"><a href="#fn:locations" class="footnote" rel="footnote">2</a></sup> that aren’t likely to participate. The effectiveness of an employee withholding their labour is basically measured by their contribution to the marginal cost of the product and that product’s place in the economy. This is evidenced at the extremes by how power attempts to limit strikes in key industries, from no-strike clauses in healthcare, the Railway Labor Act,<sup id="fnref:rla" role="doc-noteref"><a href="#fn:rla" class="footnote" rel="footnote">3</a></sup> and the union-busting of air traffic controllers.<sup id="fnref:atc" role="doc-noteref"><a href="#fn:atc" class="footnote" rel="footnote">4</a></sup></p>

<p>But that doesn’t mean that a daylong walkout—like what we’re seeing in Minneapolis today—won’t be effective. It’s just not a strike; it’s a protest.</p>

<p>While it’s easy to be tricked into thinking that nonviolent protests don’t work, the reality is that they are a visible shot across the bow of power. Protests are a reversion to direct democracy, a show of numbers by people united by a common grievance when their elected representatives fall short. They bring like-minded people together.</p>

<p>Most importantly though, protests are a threat of escalation. The <a href="https://en.wikipedia.org/wiki/3.5%25_rule">“3.5% rule” in political science</a> is intended to assess the credibility of that threat, but it’s not founded on any specific principles that make it inevitable. If you’re unhappy with things, get out there and meet people who share your view. Plan actions together that will threaten power in ways that encourage better outcomes.</p>

<p>Protests are collective action. Which makes them union as fuck.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:hourly" role="doc-endnote">
      <p>As opposed to hourly/shift <a href="#fnref:hourly" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:locations" role="doc-endnote">
      <p>Usually by offshoring production, but manufacturing animosity towards immigrants or between ethnicities also works. <a href="#fnref:locations" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:rla" role="doc-endnote">
      <p>See: <a href="https://en.wikipedia.org/wiki/2022_United_States_railroad_labor_dispute">the Biden administration’s blockade of a railroad workers’ strike in 2022</a> <a href="#fnref:rla" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:atc" role="doc-endnote">
      <p>See: <a href="https://en.wikipedia.org/wiki/1981_Professional_Air_Traffic_Controllers_Organization_strike">the Reagan administration’s strike-breaking action against air traffic controllers in 1981</a> <a href="#fnref:atc" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[Taking a day off work may not be a strike, but it is collective action.]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">Fixed Point Visualization</title>
      <link href="https://numi.st/tool/fixed-point/" rel="alternate" type="text/html" title="Fixed Point Visualization" />
      <published>2025-10-05T23:45:13+00:00</published>
      <updated>2025-10-05T23:55:20+00:00</updated>
      <id>https://numi.st/tool/fixed-point/</id>
      
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[A tool for debugging fixed-point integer representations.]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">Motorcycle Airbags</title>
      <link href="https://numi.st/post/2025/airbags/" rel="alternate" type="text/html" title="Motorcycle Airbags" />
      <published>2025-09-15T15:32:43+00:00</published>
      <updated>2025-11-10T21:46:16+00:00</updated>
      <id>https://numi.st/post/2025/airbags/</id>
      <content type="html" xml:base="https://numi.st/post/2025/airbags/"><![CDATA[<p>While my helmet was indisputably the star of <a href="/post/2024/the-crash/">the show</a> in terms of injury reduction, my airbag vest soaked up a <em>very</em> hard landing and everyone from the medics that picked me up to my riding buddies have wanted to hear more about it.</p>

<p>I bought mine in 2022 when my employer instituted a mandatory return to office policy.<sup id="fnref:seat" role="doc-noteref"><a href="#fn:seat" class="footnote" rel="footnote">1</a></sup> Moving to Oakland meant that my new commute was substantially more dangerous, and having a kid meant it was more important than ever that I not die. Nor, ideally, be maimed.</p>

<p>There are a lot of options on the market, which raises a lot of questions. The answers depend on what you’re optimizing for. Airbag systems are available with mechanical or electronic triggers. They may be integrated into gear, worn underneath, or worn on top. Different models cover different parts of the body. Here’s how I chose:</p>

<h2 id="external-internal-or-integrated">External, Internal, or Integrated?</h2>

<p>Broadly, there are three different kinds of air bag garments:</p>

<ol>
  <li>“External” vests you wear over your jacket/suit</li>
  <li>“Internal” vests you wear under your jacket/suit</li>
  <li>“Integrated” systems built into your jacket/suit</li>
</ol>

<p>Integrated solutions have a lot going for them and are worth considering if you’re shopping for a complete set of gear, but I’m very happy with my Roadcrafter so for me the question was just “external” vs “internal”.</p>

<p>Before the pandemic I rode my motorcycle every single day, which transfers a lot of sweat and grime into riding gear. My helmet’s pads and my whole suit (sans armour) are machine-washable, but at the time none of the internal airbags on the market had a better story than “use a moist rag and don’t get the inflator wet”. Nowadays some internal vests can be broken down for cleaning, but they still come with other caveats like “your jacket must have at least 4cm of extra space around the chest” which foreshadow <a href="https://www.reddit.com/r/motorcycle/comments/1kds0xm/deleted_by_user/">problems</a><sup id="fnref:deleted_by_user" role="doc-noteref"><a href="#fn:deleted_by_user" class="footnote" rel="footnote">2</a></sup> that I don’t don’t need in my life.</p>

<p>Meanwhile, the bladder of an external vest is not constrained, free to fill the gap between my shoulders and helmet. Nor, practically speaking, does it need to be cleaned. It doesn’t even add an extra step to gearing up; at this point <em>my suit</em> wears the vest and I don (or doff) them together as one.</p>

<h2 id="mechanical-or-electronic-trigger">Mechanical or Electronic Trigger?</h2>

<p>As far as I’m aware only external vests and <em>some</em> integrated systems offer mechanical triggers, which connect to a tether attached to the motorcycle. These are very simple systems—yanking on the tether with around 60 lbs of force triggers the inflator, which does its job in the blink of an eye.</p>

<p>Electronically-triggered airbags use advanced machine learning algorithms fed by GPS data and multiple <abbr title="Inertial Measurement Unit, a chip containing 3 axes each of accelerometer, gyroscope, and (usually) magnetic compass">IMU</abbr>s. Some can communicate with an additional IMU on the motorcycle,<sup id="fnref:differential" role="doc-noteref"><a href="#fn:differential" class="footnote" rel="footnote">3</a></sup> some support multiple deployments before the inflator is discharged, and they can all react (and deploy) before the rider even realizes they’re crashing.</p>

<p>They also don’t work when the battery is dead and require factory service after discharge. Many models only fire at GPS speeds greater than 15 mph<sup id="fnref:stoplight" role="doc-noteref"><a href="#fn:stoplight" class="footnote" rel="footnote">4</a></sup> and some manufacturers engage in <a href="https://www.bennetts.co.uk/bikesocial/reviews/products/motorcycle-armour-and-base-layers/inemotion-airbag-vest-review-safety">pretty unsavoury pricing practices</a>.</p>

<p>I chose the tether. I like that I can check if it’s “on” by giving the tether a tug. I’d gone down with it once before, but the airbag didn’t deploy because <em>I stayed on the bike</em>, having lowsided at low speed in a mud patch. This was a fine outcome for me because there was also no real threat of injury—I even had enough time to kill the engine on the way down—but if it <em>had</em> deployed, the propellant is a standard threaded 60 cc CO₂ cartridge and the spring-loaded trigger mechanism can be reset on the side of the road with an Allen key.</p>

<p>It’s easy to imagine downsides to mechanical tethers, but they don’t really come up in practice. I’ve figured out how to connect the buckle with one hand while I’m riding,<sup id="fnref:fidlock" role="doc-noteref"><a href="#fn:fidlock" class="footnote" rel="footnote">5</a></sup> but rarely forget to do it before taking off. If I forget to unbuckle when dismounting, the trigger’s minimum force provides feedback that’s pretty difficult to ignore.<sup id="fnref:jump" role="doc-noteref"><a href="#fn:jump" class="footnote" rel="footnote">6</a></sup> One company in Europe uses an <a href="https://www.motoairbag.com/en/shop/accessories-and-refills/upgrade-to-fast-lock/">inertial reel</a> for their tether (instead of a nylon-webbed bungee), which guarantees the fastest possible deployment for a mechanical system without compromising the rider’s ability to stand up on the pegs.</p>

<h2 id="coverage">Coverage</h2>

<p>When I was first shopping, internal vests were sized for fitting under jackets, which limited their coverage. External vests extended further, with the bladder overlapping the rider’s hips and tailbone. Nowadays maximalists that don’t mind spending more time getting dressed can choose internal (or integrated) airbag systems with coverage all the way out to the rider’s wrists and thighs.</p>

<p>Collarbone fractures are the most common injury among riders wearing passive protection. Hip fractures are less common, but affect your mobility for the rest of your life. My goal was not to prevent <em>all</em> injuries, but to minimize long-term impacts. Your goals may be different—and it’s totally reasonable to want maximum coverage—but past a certain point optimizing for this favours internal or integrated systems; if you’re inclined towards a mechanical trigger, you may have to compromise.</p>

<h2 id="anything-else">Anything Else?</h2>

<p>If you made it this far, I chose the Helite Turtle 2. The fabric around its back armour has seen better days, but it’s still serviceable and I’m still wearing it on the commute. I’m planning on buying a Helite H-MOOV as soon as someone will sell one to me.</p>

<p>In 2021 Ryan F9 posted <a href="https://www.youtube.com/watch?v=N2jZryt607U">a pretty good video about airbags</a> (he also preferred the mechanical Helite) and in 2024 he posted <a href="https://www.youtube.com/watch?v=moQ08uyiYls">another</a> (same). Note that <em>he’s not an <abbr title="All The Gear, All The Time">ATGATT</abbr> guy</em>, and that his (and my) perspective is focused on the hazards of street riding. Maybe you’re shopping for the track. Maybe you think bulky vests with tethers look dorky.<sup id="fnref:dork" role="doc-noteref"><a href="#fn:dork" class="footnote" rel="footnote">7</a></sup> Everyone’s needs are different and ultimately my choices may be different from yours, but hopefully reading this can help you decide what’s best for you. All I can say for sure is that crashing with an airbag is wayy better than crashing without one.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:seat" role="doc-endnote">
      <p>I also treated myself to a <a href="/post/2022/the-zero-gets-a-corbin/">comfier seat</a> <a href="#fnref:seat" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:deleted_by_user" role="doc-endnote">
      <p>Archived by <a href="https://www.advrider.com/f/threads/dangers-of-airbag-vests-probably-limited-to-a-specific-model.1793079/">ADVrider</a> <a href="#fnref:deleted_by_user" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:differential" role="doc-endnote">
      <p>Using differential readings to determine when you part ways <a href="#fnref:differential" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:stoplight" role="doc-endnote">
      <p>Which seems fine until you get rear-ended at a stoplight, or crash in a tunnel <a href="#fnref:stoplight" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:fidlock" role="doc-endnote">
      <p>Thinking every time that the tether’s buckle would be a perfect application for a sturdy Fidlock <a href="#fnref:fidlock" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:jump" role="doc-endnote">
      <p>Or overcome, the only time I’ve seen an accidental discharge from a tether system was when the rider literally jumped off of the motorcycle <a href="#fnref:jump" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:dork" role="doc-endnote">
      <p>They do; I am perennially uncool <a href="#fnref:dork" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[They're good]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">Unicode Fraction Generator</title>
      <link href="https://numi.st/tool/fractions/" rel="alternate" type="text/html" title="Unicode Fraction Generator" />
      <published>2025-03-21T21:49:09+00:00</published>
      <updated>2025-10-05T23:55:20+00:00</updated>
      <id>https://numi.st/tool/fractions/</id>
      
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[A tool for generating fractions in Unicode.]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">Data Loss</title>
      <link href="https://numi.st/post/2025/data-loss/" rel="alternate" type="text/html" title="Data Loss" />
      <published>2025-03-21T03:14:14+00:00</published>
      <updated>2025-03-27T19:11:30+00:00</updated>
      <id>https://numi.st/post/2025/data-loss/</id>
      <content type="html" xml:base="https://numi.st/post/2025/data-loss/"><![CDATA[
              
                <p>I had a major data loss event in 2013 and have been gradually piecing things back together since then.</p>
              
              <p>This post is not readable in the feed due to <a href="https://github.com/numist/numi.st/issues/120">a bug</a>, follow <a href="https://numi.st/post/2025/data-loss/">this link</a> to check it out in your browser!</p>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[I had a major data loss event in 2013 and have been gradually piecing things back together since then.]]></summary>
      

      
      
        
        <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://numi.st/IMG_5448.jpg" />
        <media:content medium="image" url="https://numi.st/IMG_5448.jpg" xmlns:media="http://search.yahoo.com/mrss/" />
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">Crying in the Shower</title>
      <link href="https://numi.st/post/2025/crying-in-the-shower/" rel="alternate" type="text/html" title="Crying in the Shower" />
      <published>2025-01-09T05:42:32+00:00</published>
      <updated>2025-01-09T05:46:12+00:00</updated>
      <id>https://numi.st/post/2025/crying-in-the-shower/</id>
      <content type="html" xml:base="https://numi.st/post/2025/crying-in-the-shower/"><![CDATA[<p>When Square had a liquidity event in early 2014 someone<sup id="fnref:who" role="doc-noteref"><a href="#fn:who" class="footnote" rel="footnote">1</a></sup> shared their “crying in the shower” approach to investing with me:</p>

<blockquote>
  <p>Sell enough that you’re not crying in the shower if the company goes out of business tomorrow, but not so much that you’re crying in the shower if the stock goes up 100⨉ in ten years.</p>
</blockquote>

<p>So I sold enough to become debt-free, and got fired shortly after that<sup id="fnref:fired" role="doc-noteref"><a href="#fn:fired" class="footnote" rel="footnote">2</a></sup>. I bought up what I could afford in the following weeks<sup id="fnref:modest" role="doc-noteref"><a href="#fn:modest" class="footnote" rel="footnote">3</a></sup>, SQ did make it to 100⨉ above my strike in 2021, and at no point was I crying in the shower over my investment decisions!</p>

<p>Best advice I ever got.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:who" role="doc-endnote">
      <p>I’d love to give attribution but I can’t remember who, even after of asking around. If you remember, please let me know. <a href="#fnref:who" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:fired" role="doc-endnote">
      <p>The person who fired me was out soon after, which felt exonerating. <a href="#fnref:fired" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:modest" role="doc-endnote">
      <p>Which wasn’t much, having paid off all my debt so recently. <a href="#fnref:modest" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[A simple guide for making risky investment decisions]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">CSV Tables in Jekyll</title>
      <link href="https://numi.st/code/csv/" rel="alternate" type="text/html" title="CSV Tables in Jekyll" />
      <published>2024-10-31T03:54:57+00:00</published>
      <updated>2025-10-05T23:57:12+00:00</updated>
      <id>https://numi.st/code/csv/</id>
      <content type="html" xml:base="https://numi.st/code/csv/"><![CDATA[
              
                <p>For when the Markdown syntax is too annoying to work with.</p>
              
              <p>This post is not readable in the feed due to <a href="https://github.com/numist/numi.st/issues/120">a bug</a>, follow <a href="https://numi.st/code/csv/">this link</a> to check it out in your browser!</p>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[For when the Markdown syntax is too annoying to work with.]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">The Crash</title>
      <link href="https://numi.st/post/2024/the-crash/" rel="alternate" type="text/html" title="The Crash" />
      <published>2024-10-30T06:56:27+00:00</published>
      <updated>2024-10-31T06:19:56+00:00</updated>
      <id>https://numi.st/post/2024/the-crash/</id>
      <content type="html" xml:base="https://numi.st/post/2024/the-crash/"><![CDATA[
              
                <p><p>My commute home from work did not go as planned.</p>
</p>
              
              <p>This post is not readable in the feed due to <a href="https://github.com/numist/numi.st/issues/120">a bug</a>, follow <a href="https://numi.st/post/2024/the-crash/">this link</a> to check it out in your browser!</p>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[My commute home from work did not go as planned.]]></summary>
      

      
      
        
        <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://numi.st/post/2024/the-crash/IMG_4933.jpeg" />
        <media:content medium="image" url="https://numi.st/post/2024/the-crash/IMG_4933.jpeg" xmlns:media="http://search.yahoo.com/mrss/" />
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">`mmap` Considered Harmful</title>
      <link href="https://numi.st/post/2024/mmap/" rel="alternate" type="text/html" title="`mmap` Considered Harmful" />
      <published>2024-10-18T06:10:17+00:00</published>
      <updated>2025-09-06T19:30:57+00:00</updated>
      <id>https://numi.st/post/2024/mmap/</id>
      <content type="html" xml:base="https://numi.st/post/2024/mmap/"><![CDATA[<p><a href="https://sqlite.org/forum/forumpost/3ce1ee76242cfb29">Richard</a>, as <a href="https://simonwillison.net/2024/Oct/18/d-richard-hipp/">quoted by Simon Willison</a>:</p>

<blockquote>
  <p>I’m of the opinion that you should never use mmap, because if you get an I/O error of some kind, the OS raises a signal, which SQLite is unable to catch, and so the process dies. When you are not using mmap, SQLite gets back an error code from an I/O error and is able to take remedial action, or at least compose an error message.</p>
</blockquote>

<p>I have ranted about <code class="language-plaintext highlighter-rouge">mmap</code><sup id="fnref:files" role="doc-noteref"><a href="#fn:files" class="footnote" rel="footnote">1</a></sup> on this site <a href="/post/2022/objc-defer/#fn:mmap">before</a>, and avoidable crashes <em>ought</em> to be a compelling reason to avoid it, but people still use it! Perhaps it would help to ask <em>why</em>:</p>

<h2 id="performance">Performance</h2>

<p>This is the usual reason people give. “<code class="language-plaintext highlighter-rouge">mmap</code> is faster” is usually supported by two reasons: syscall overhead and buffer copying.</p>

<p>Syscalls were an uncommon bottleneck twenty years ago, and overhead for common syscalls (like <code class="language-plaintext highlighter-rouge">pread</code>) have decreased significantly since then. These days their overhead is a rounding error compared to the work they perform.</p>

<p>Likewise, the people in userland whose performance depends on zero-copy techniques are <em>writing</em> filesystems, not <em>using</em> them<sup id="fnref:vmx" role="doc-noteref"><a href="#fn:vmx" class="footnote" rel="footnote">2</a></sup>. <abbr title="Virtual Memory">VM</abbr> <abbr title="Copy on Write">CoW</abbr> is good enough for the remaining people who can express their work units as some multiple of the VM’s page size.</p>

<h2 id="shared-memory">Shared Memory</h2>

<p>SQLite uses <code class="language-plaintext highlighter-rouge">mmap</code><sup id="fnref:wal" role="doc-noteref"><a href="#fn:wal" class="footnote" rel="footnote">3</a></sup> for manifesting path-addressible garbage-collected interprocess shared memory regions, which is the only reason I’ve found for which there is no other option. A POSIX shmem can’t be reliably associated with a database when the process is <code class="language-plaintext highlighter-rouge">chroot</code>ed and will leak if the last process using it dies without releasing its claim first, which is super common on platforms with aggressive oom behaviour (like iOS).</p>

<p>So this is where I step back from the doomerism a bit. Practically speaking, the combination of file monitoring via <a href="https://developer.apple.com/documentation/dispatch/dispatch_source_type_vnode?language=objc"><code class="language-plaintext highlighter-rouge">DISPATCH_SOURCE_TYPE_VNODE</code></a> and the strategic use of <a href="https://developer.apple.com/documentation/kernel/1402127-mach_vm_read_overwrite"><code class="language-plaintext highlighter-rouge">mach_vm_read_overwrite</code></a> when significant time has elapsed since the last access has, in practice, almost entirely eliminated <code class="language-plaintext highlighter-rouge">mmap</code>-related crashes in SQLite (the API will return <code class="language-plaintext highlighter-rouge">SQLITE_IOERR_VNODE</code> (6922) instead) with no measureable performance cost. But these mitigations are <em>so much more complicated</em> than “an API that returns an error if it fails”, which brings us finally to the <em>real</em> reason people use <code class="language-plaintext highlighter-rouge">mmap</code>,</p>

<h2 id="convenience">Convenience</h2>

<p><code class="language-plaintext highlighter-rouge">mmap</code> is from a time before APIs expressed their own opinions intentionally<sup id="fnref:opinions" role="doc-noteref"><a href="#fn:opinions" class="footnote" rel="footnote">4</a></sup> and its ease of use makes it an extremely attractive nuisance. Nobody likes to admit to being lazy, but for files of arbitrary size (like databases), jumping around with pointer arithmetic is hard to beat: one bounds check<sup id="fnref:oob" role="doc-noteref"><a href="#fn:oob" class="footnote" rel="footnote">5</a></sup> and no memory management. Humans follow incentives, and C provides an environment where it’s way easier to ignore errors than to handle them. Consider what SQLite does instead, roughly 8,000 lines of code <a href="https://www.sqlite.org/src/file?udc=1&amp;ln=on&amp;ci=trunk&amp;name=src%2Fpager.c">implementing</a> a <a href="">pager</a>https://www.sqlite.org/src/file?udc=1&amp;ln=on&amp;ci=trunk&amp;name=src%2Fpager.h and <a href="https://www.sqlite.org/src/file?udc=1&amp;ln=on&amp;ci=trunk&amp;name=src%2Fpcache.c">another</a> 2,000 <a href="https://www.sqlite.org/src/file?udc=1&amp;ln=on&amp;ci=trunk&amp;name=src%2Fpcache1.c">implementing</a> a <a href="https://www.sqlite.org/src/file?udc=1&amp;ln=on&amp;ci=trunk&amp;name=src%2Fpcache.h">page cache</a>. It’s hard to blame people for making one call to <code class="language-plaintext highlighter-rouge">mmap</code> when the alternative is maintaining an additional 10k<abbr title="Lines of Code">LoC</abbr> to do it properly!  <!--, which can be largely be defined in terms of the amount of load it bears. SQLite is probably the most load-bearing userland software in existence and [its qualification practices](https://www.sqlite.org/testing.html) reflect that. _Of course_ Richard will tell you not to use `mmap`-->.</p>

<p>The solution here is basically one of progress. CISA and the FBI <a href="https://www.cisa.gov/resources-tools/resources/product-security-bad-practices">have asked vendors to provide memory-safety roadmaps by 2026</a>; while it’s possible to <a href="https://clang.llvm.org/docs/BoundsSafety.html">improve the memory safety of C code</a>, these solutions are not complete<sup id="fnref:lifetime" role="doc-noteref"><a href="#fn:lifetime" class="footnote" rel="footnote">6</a></sup>. Languages built with memory safety by default tend to include syntax that make errors harder to ignore than to handle and include standard libraries with more ergonomic (and opinionated) abstractions for things like file I/O.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:files" role="doc-endnote">
      <p>I am going to use <code class="language-plaintext highlighter-rouge">mmap</code> to refer specifically to the creation of file-backed memory maps. This is not strictly correct—there are map types other than <code class="language-plaintext highlighter-rouge">MAP_FILE</code>—but it is colloquial. <a href="#fnref:files" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:vmx" role="doc-endnote">
      <p>Also virtual machines, at least circa 2010 when I helped get our hardware accelerated 3D graphics stack down to zero copies within the scope of the vmx. It has been <em>very funny</em> to watch Apple Silicon’s <abbr title="Unified Memory Architecture">UMA</abbr> do the same thing in hardware. <a href="#fnref:vmx" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:wal" role="doc-endnote">
      <p>For the <a href="https://www.sqlite.org/walformat.html#the_wal_index_file_format">wal index</a>. <a href="#fnref:wal" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:opinions" role="doc-endnote">
      <p>These days, languages and their libraries can conspire so “bad” code is more difficult to write than “good” code. This was never the case with POSIX interfaces and remains rare among syscalls in general. <a href="#fnref:opinions" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:oob" role="doc-endnote">
      <p>Hopefully. At least. <a href="#fnref:oob" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:lifetime" role="doc-endnote">
      <p><code class="language-plaintext highlighter-rouge">-fbounds-safety</code> does not help with lifetime issues, for example. <a href="#fnref:lifetime" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[So why do people keep using it?]]></summary>
      

      
      
    </entry>
  
    <!-- We need to differentiate posts vs pages here because post.content is pre-rendered but page.content is not -->
    
    <entry>
      

      <title type="html">On Steam Power</title>
      <link href="https://numi.st/post/2024/on-steam-power/" rel="alternate" type="text/html" title="On Steam Power" />
      <published>2024-09-24T07:35:36+00:00</published>
      <updated>2024-09-24T16:27:50+00:00</updated>
      <id>https://numi.st/post/2024/on-steam-power/</id>
      <content type="html" xml:base="https://numi.st/post/2024/on-steam-power/"><![CDATA[<p>Surprising nobody, one topic of conversation following my <a href="/post/2024/the-power-tool-era-of-software/">post about power tools</a> was the environmental impact of generative models, and “are these new tools worth the cost?” is an entirely valid follow-up question. Running these models is incredibly expensive, with energy and water consumption numbers that boggle the mind—datacenters belonging to Google, Microsoft, and Meta consumed approximately 2.2×10⁹ m³ of water in 2022<sup id="fnref:ai-water" role="doc-noteref"><a href="#fn:ai-water" class="footnote" rel="footnote">1</a></sup>!</p>

<p>That’s 0.5% of the 444.4×10⁹ m³ consumed by the United States alone in 2020<sup id="fnref:global-water" role="doc-noteref"><a href="#fn:global-water" class="footnote" rel="footnote">2</a></sup>, but people <em>need</em> food and <em>don’t need</em>, as one person put it, “bullshit factories”. Which is true! I don’t need “spicy autocomplete” to write code any more than I need a router to cut a rabbet, but both are useful and neither are going away. To continue with the metaphors: these new power tools are themselves in their steam power era.</p>

<p>Steam power is a nice label that helps historians<sup id="fnref:thomas" role="doc-noteref"><a href="#fn:thomas" class="footnote" rel="footnote">3</a></sup> avoid having to mention coal. The initial mechanization of all industries (including carpentry) came at such a high environmental cost that “a black form of the peppered moth rapidly took over in industrial parts of the UK during the 1800s, as soot blackened the tree trunks and walls of its habitat”<sup id="fnref:peppered-moth" role="doc-noteref"><a href="#fn:peppered-moth" class="footnote" rel="footnote">4</a></sup>.</p>

<p>The early days of the Industrial Revolution were <em>grim</em>, but there’s not much coal left in today’s industrial power mix—the UK is even on track to shut down their last plant this year<sup id="fnref:uk-coal" role="doc-noteref"><a href="#fn:uk-coal" class="footnote" rel="footnote">5</a></sup>. This has mostly been made possible by a combination of electrification and improved grid composition, and the impact has been significant. In 2020, 70.6% of domestically-produced steel in the United States was made by electric arc furnace<sup id="fnref:steel" role="doc-noteref"><a href="#fn:steel" class="footnote" rel="footnote">6</a></sup> and 59% of California’s electricity came from carbon-free sources<sup id="fnref:cec" role="doc-noteref"><a href="#fn:cec" class="footnote" rel="footnote">7</a></sup>.</p>

<p>Likewise there are already improvements happening today that directly map to modern datacenters. Within the past decade many municipal utilities have added high quality recycled water (or <a href="https://www.valleywater.org/news-events/news-releases/recycled-water-runs-through-it-purple-pipe-system">“purple” water</a>) to their offerings, and renewable sources in Europe now regularly cause power production to exceed demand, resulting in negative electricity prices<sup id="fnref:negative-energy" role="doc-noteref"><a href="#fn:negative-energy" class="footnote" rel="footnote">8</a></sup>.</p>

<p>There <em>is</em> cause for optimism, and <a href="https://kottke.org/24/08/hopefulness-is-the-warrior-emotion">it’s important that we let ourselves feel that</a>. If anything, it’s inspiring that people’s access to information today has improved so much that the costs of datacenters—which do not directly affect most people!—are such common knowledge; it only adds to the incentives pressuring them to improve.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:ai-water" role="doc-endnote">
      <p>Li, Pengfei et. al. <a href="https://arxiv.org/pdf/2304.03271">Making AI Less “Thirsty”: Uncovering and Addressing the Secret Water Footprint of AI Models</a>. <em>arXiv</em>, 6 Apr. 2023. <a href="#fnref:ai-water" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:global-water" role="doc-endnote">
      <p>Ritchie, Hannah, and Max Roser. <a href="https://ourworldindata.org/water-use-stress#:~:text=Freshwater%20withdrawals%20by%20country">Water Use and Stress</a>. <em>Our World in Data</em>, Feb. 2024. <a href="#fnref:global-water" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:thomas" role="doc-endnote">
      <p>And kids’ shows like Thomas the Tank Engine. <a href="#fnref:thomas" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:peppered-moth" role="doc-endnote">
      <p>Webb, Jonathan. <a href="https://www.bbc.com/news/science-environment-36424768">Famous Peppered Moth’s Dark Secret Revealed</a>. <em>BBC News</em>, 1 June 2016. <a href="#fnref:peppered-moth" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:uk-coal" role="doc-endnote">
      <p>Calma, Justine. <a href="https://www.theverge.com/2024/9/23/24252195/last-coal-power-plant-close-climate-change-clean-energy">The UK Helped Usher in the Coal Era — Now It’s Closing Its Last Remaining Plant</a>. <em>The Verge</em>, 23 Sept. 2024 <a href="#fnref:uk-coal" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:steel" role="doc-endnote">
      <p><a href="https://www.steel.org/wp-content/uploads/2021/11/AISI_FactSheet_SteelSustainability-11-3-21.pdf">Facts about American Steel Sustainability</a>. <em>American Iron and Steel Institute</em>. <a href="#fnref:steel" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:cec" role="doc-endnote">
      <p><a href="https://www.energy.ca.gov/news/2022-02/new-data-indicates-california-remains-ahead-clean-electricity-goals">New Data Indicates California Remains ahead of Clean Electricity Goals</a>. <em>California Energy Commission</em>, 22 Feb. 2022. <a href="#fnref:cec" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:negative-energy" role="doc-endnote">
      <p>Bocca, Roberto. <a href="https://www.weforum.org/agenda/2024/09/negative-energy-price-record-in-europe-and-other-top-energy-stories/">Negative Energy Price Record in Europe, and Other Top Energy Stories</a>. <em>World Economic Forum</em>, 23 Sept. 2024. <a href="#fnref:negative-energy" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content>
      
      
      
      

      <author>
          <name>Scott Perry</name>
        
        
      </author>

      

      

      
      
        <summary type="html"><![CDATA[And why doomerism gets us nowhere.]]></summary>
      

      
      
    </entry>
  
</feed>