# rss_item

guid: https://richiejp.com/1d-reversible-automata
title: Bitbanging 1D Reversible Automata
author: Richard Palethorpe
url: https://richiejp.com/1d-reversible-automata
feedurl: https://richiejp.com/atom.xml
content_mime_type: application/xhtml+xml
content:
    <div xmlns="http://www.w3.org/1999/xhtml">
            <h1 id="one-dimensional-reversible-automata">One Dimensional
            Reversible Automata</h1>
            <p>I created a <a href="https://github.com/gfxprim/automata">demo</a> for the
            <a href="http://gfxprim.ucw.cz/index.html">GFXPrim</a>
            library. It implements and displays a nearest-neighbor,
            one-dimensional, binary cell automata. Additionally it
            implements a reversible automata, which is almost identical
            except for a small change to make it reversible. The
            automata is displayed over time in two dimensions, time
            travels from top to bottom. Although in the reversible case
            time could be played backwards.</p>
            <div class="message is-info">
            <div class="message-body">
            <p>There is now a <a href="1d-reversible-automata-webgpu">WebGPU version you can
            try out in your browser!</a></p>
            </div>
            </div>
            <div class="float">
            <img src="/73r.png" alt="A reversible rendition of rule 73"/>
            <div class="figcaption">A reversible rendition of rule
            73</div>
            </div>
            <p>The automata works as follows:</p>
            <ul>
            <li>Each cell has a state, which is on or off, black or
            white, boolean etc.</li>
            <li>At each time step, the state of a cell in the next step
            is chosen by a rule.</li>
            <li>The rule looks at a cell’s current value and the values
            of its left and right neighbors.</li>
            <li>There are <span class="math inline">2<sup>3</sup> = 8</span> possible state
            combinations (patterns) for 3 binary cells.</li>
            <li>A rule states which patterns result in a black cell in
            the next time step.</li>
            <li>There are <span class="math inline">2<sup>8</sup> = 256</span> possible
            rules. That is, 256 unique combinations of patterns.</li>
            </ul>
            <div class="float">
            <img src="/105.png" alt="Rule 105"/>
            <div class="figcaption">Rule 105</div>
            </div>
            <p>So a pattern is a 3 digit binary number, where each digit
            corresponds to a cell. The middle digit is the center cell,
            the high order bit the left cell, the low order bit the
            right cell. A rule can be display by showing a row of
            patterns and a row of next states.</p>
            <table>
            <thead>
            <tr class="header">
            <th align="center">111</th>
            <th align="center">110</th>
            <th align="center">101</th>
            <th align="center">100</th>
            <th align="center">011</th>
            <th align="center">010</th>
            <th align="center">001</th>
            <th align="center">000</th>
            </tr>
            </thead>
            <tbody>
            <tr class="odd">
            <td align="center">0</td>
            <td align="center">1</td>
            <td align="center">1</td>
            <td align="center">0</td>
            <td align="center">1</td>
            <td align="center">1</td>
            <td align="center">1</td>
            <td align="center">0</td>
            </tr>
            </tbody>
            </table>
            <p>Above is rule <code>110</code>, <code>0x6e</code> or
            <code>01101110</code>. It essentially says to match patterns
            <code>110</code>, <code>101</code>, <code>011</code>,
            <code>010</code>, <code>001</code>. Where a pattern match
            results in the cell being set to 1 at the next time step. If
            no pattern is matched or equivalently, an inactive pattern
            is matched, then the cell will be set to 0.</p>
            <p>Again note that each pattern resembles a 3bit binary
            number. Also the values of the active patterns resemble an
            8bit binary number. We can use this to perform efficient
            matching of the patterns using binary operations.</p>
            <p>Let’s assume our CPU natively operates on 64bit integers
            (called <em>words</em>). We can pack a 64 cell automata into
            a single 64bit integer. Each bit corresponds to a cell. If a
            bit is <code>1</code> then it is a black cell and
            <code>0</code> for white. In this case we are using integers
            as bit fields. We don’t care about the integer number the
            bits can represent.</p>
            <div class="float">
            <img src="/94r.png" alt="Rule 94 Reversible"/>
            <div class="figcaption">Rule 94 Reversible</div>
            </div>
            <p>The CPU can perform bitwise operations on all 64bits in
            parallel and without branching. This means we can perform a
            single operation 64 times in parallel.<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a></p>
            <p>If we <em>rotate</em> (wrapped <code>&gt;&gt;</code><a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a>) all bits to the right by one,
            then we get a new integer where the left neighbor of a bit
            is now in its position. Likewise if we shift all bits to the
            left, then we get an integer representing the right
            neighbors. This gives us 3 integers where the left, center
            and right bits are in the same position. For example, using
            only 8bits:</p>
            <table>
            <tbody>
            <tr class="odd">
            <td align="left">left:</td>
            <td>0100 1011</td>
            <td><code>&gt;&gt;</code></td>
            </tr>
            <tr class="even">
            <td align="left">center:</td>
            <td>1001 0110</td>
            <td/>
            </tr>
            <tr class="odd">
            <td align="left">right:</td>
            <td>0010 1101</td>
            <td><code>&lt;&lt;</code></td>
            </tr>
            </tbody>
            </table>
            <p>Each pattern can be represented as a 3bit number, plus a
            4th bit to say whether it is active in a given rule. As we
            want to operate on all 64bits at once in the left, right and
            center bit fields. We can generate 64bit long <em>masks</em>
            from the value of each bit in a given pattern.</p>
            <p>So if we have a pattern where the left cell should be
            one, then we can create a 64bit mask of <em>all</em> ones.
            If it should be zero, then all zeroes. Likewise for the
            center and right cells. The masks can be <em>xor’ed</em><a href="#fn3" class="footnote-ref" id="fnref3"><sup>3</sup></a> (<code>^</code>) with the
            corresponding cell fields to show if no match occurred. That
            is, if the pattern is one and the cell is zero or the cell
            is one and the pattern is zero. We can invert this
            (<code>~</code>) to give one when a match occurs.</p>
            <p>To see whether all components (left, right, center) of a
            pattern matches we can bitwise <em>and</em>
            (<code>&amp;</code>) them together. We can then bitwise
            <em>or</em><a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a> (<code>|</code>) the result of
            the pattern matches together to produce the final
            values.</p>
            <div class="float">
            <img src="/193.jpg" alt="Rule 193, inverted rule 110"/>
            <div class="figcaption">Rule 193, inverted rule 110</div>
            </div>
            <p>If we wish to operate on an automata larger than 64
            cells, then we can combine multiple integers into an array.
            After performing the left and right shifts, we get the high
            or low bit from the next or previous integers in the array.
            Then set the low and high bits of the right and left bit
            fields. In other words we chain them together using the end
            bits of the left and right bit fields.</p>
            <p>For illustration purposes, below is the <em>kernel</em>
            of the the automata algorithm.</p>
            <div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" tabindex="-1"/><span class="co">/* If bit n is 1 then make all bits 1 otherwise 0 */</span></span>
<span id="cb1-2"><a href="#cb1-2" tabindex="-1"/><span class="pp">#define BIT_TO_MAX</span><span class="op">(</span><span class="pp">b</span><span class="op">,</span><span class="pp"> n</span><span class="op">)</span><span class="pp"> </span><span class="op">(((</span><span class="pp">b </span><span class="op">&gt;&gt;</span><span class="pp"> n</span><span class="op">)</span><span class="pp"> </span><span class="op">&amp;</span><span class="pp"> </span><span class="dv">1</span><span class="op">)</span><span class="pp"> </span><span class="op">*</span><span class="pp"> </span><span class="op">~</span><span class="dv">0</span><span class="bu">UL</span><span class="op">)</span></span>
<span id="cb1-3"><a href="#cb1-3" tabindex="-1"/></span>
<span id="cb1-4"><a href="#cb1-4" tabindex="-1"/><span class="co">/* Numeric representation of the current update rule */</span></span>
<span id="cb1-5"><a href="#cb1-5" tabindex="-1"/><span class="dt">static</span> <span class="dt">uint8_t</span> rule <span class="op">=</span> <span class="dv">110</span><span class="op">;</span></span>
<span id="cb1-6"><a href="#cb1-6" tabindex="-1"/></span>
<span id="cb1-7"><a href="#cb1-7" tabindex="-1"/><span class="co">/* Apply the current rule to a 64bit segment of a row */</span></span>
<span id="cb1-8"><a href="#cb1-8" tabindex="-1"/><span class="dt">static</span> <span class="kw">inline</span> <span class="dt">uint64_t</span> ca1d_rule_apply<span class="op">(</span><span class="dt">uint64_t</span> c_prev<span class="op">,</span></span>
<span id="cb1-9"><a href="#cb1-9" tabindex="-1"/>                                       <span class="dt">uint64_t</span> c<span class="op">,</span></span>
<span id="cb1-10"><a href="#cb1-10" tabindex="-1"/>                                       <span class="dt">uint64_t</span> c_next<span class="op">,</span></span>
<span id="cb1-11"><a href="#cb1-11" tabindex="-1"/>                                       <span class="dt">uint64_t</span> c_prev_step<span class="op">)</span></span>
<span id="cb1-12"><a href="#cb1-12" tabindex="-1"/><span class="op">{</span></span>
<span id="cb1-13"><a href="#cb1-13" tabindex="-1"/>    <span class="dt">int</span> i<span class="op">;</span></span>
<span id="cb1-14"><a href="#cb1-14" tabindex="-1"/>    <span class="co">/* These are wrapping shifts when c_prev == c or c_next == c */</span></span>
<span id="cb1-15"><a href="#cb1-15" tabindex="-1"/>    <span class="dt">uint64_t</span> l <span class="op">=</span> <span class="op">(</span>c <span class="op">&gt;&gt;</span> <span class="dv">1</span><span class="op">)</span> <span class="op">^</span> <span class="op">(</span>c_prev <span class="op">&lt;&lt;</span> <span class="dv">63</span><span class="op">);</span></span>
<span id="cb1-16"><a href="#cb1-16" tabindex="-1"/>    <span class="dt">uint64_t</span> r <span class="op">=</span> <span class="op">(</span>c <span class="op">&lt;&lt;</span> <span class="dv">1</span><span class="op">)</span> <span class="op">^</span> <span class="op">(</span>c_next <span class="op">&gt;&gt;</span> <span class="dv">63</span><span class="op">);</span></span>
<span id="cb1-17"><a href="#cb1-17" tabindex="-1"/>    <span class="dt">uint64_t</span> c_next_step <span class="op">=</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb1-18"><a href="#cb1-18" tabindex="-1"/></span>
<span id="cb1-19"><a href="#cb1-19" tabindex="-1"/>    <span class="cf">for</span> <span class="op">(</span>i <span class="op">=</span> <span class="dv">0</span><span class="op">;</span> i <span class="op">&lt;</span> <span class="dv">8</span><span class="op">;</span> i<span class="op">++)</span> <span class="op">{</span></span>
<span id="cb1-20"><a href="#cb1-20" tabindex="-1"/>        <span class="dt">uint64_t</span> active <span class="op">=</span> BIT_TO_MAX<span class="op">(</span>rule<span class="op">,</span> i<span class="op">);</span></span>
<span id="cb1-21"><a href="#cb1-21" tabindex="-1"/>        <span class="dt">uint64_t</span> left   <span class="op">=</span> BIT_TO_MAX<span class="op">(</span>i<span class="op">,</span> <span class="dv">2</span><span class="op">);</span></span>
<span id="cb1-22"><a href="#cb1-22" tabindex="-1"/>        <span class="dt">uint64_t</span> center <span class="op">=</span> BIT_TO_MAX<span class="op">(</span>i<span class="op">,</span> <span class="dv">1</span><span class="op">);</span></span>
<span id="cb1-23"><a href="#cb1-23" tabindex="-1"/>        <span class="dt">uint64_t</span> right  <span class="op">=</span> BIT_TO_MAX<span class="op">(</span>i<span class="op">,</span> <span class="dv">0</span><span class="op">);</span></span>
<span id="cb1-24"><a href="#cb1-24" tabindex="-1"/></span>
<span id="cb1-25"><a href="#cb1-25" tabindex="-1"/>        c_next_step <span class="op">|=</span></span>
<span id="cb1-26"><a href="#cb1-26" tabindex="-1"/>            active <span class="op">&amp;</span> <span class="op">~(</span>left <span class="op">^</span> l<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span>center <span class="op">^</span> c<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span>right <span class="op">^</span> r<span class="op">);</span></span>
<span id="cb1-27"><a href="#cb1-27" tabindex="-1"/>    <span class="op">}</span></span>
<span id="cb1-28"><a href="#cb1-28" tabindex="-1"/></span>
<span id="cb1-29"><a href="#cb1-29" tabindex="-1"/>    <span class="co">/* The automata becomes reversible when we use c_prev_state */</span></span>
<span id="cb1-30"><a href="#cb1-30" tabindex="-1"/>    <span class="cf">return</span> c_next_step <span class="op">^</span> c_prev_step<span class="op">;</span></span>
<span id="cb1-31"><a href="#cb1-31" tabindex="-1"/><span class="op">}</span></span></code></pre></div>
            <p>To make the automata “reversible” an extra step can be
            added. We look at a cell’s previous (in addition to the
            current, left and right) and if it was one then
            <em>invert</em> the next value. This is equivalent to
            xor’ring the previous value with the next.</p>
            <div class="float">
            <img src="/193r.jpg" alt="Rule 193 again, but reversible"/>
            <div class="figcaption">Rule 193 again, but reversible</div>
            </div>
            <p>It is not entirely clear to me what the mathematical
            implications are of being reversible. However it is
            important to physics and makes some really cool patterns
            which mimic nature. Also entropy and the second rule of
            themodynamics, yada, yada…</p>
            <p>The automata definition is taken from Stephen Wolfram’s
            “A new kind of science”. He proposes at least one
            <em>obvious</em><a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a> C implementation using arrays
            of cells. He also provides a table of binary expressions for
            each rule. E.g. rule 90 reduces to just the <code>l^r</code>
            binary expression. It may be possible for the compiler to
            automatically reduce my implementation to these minimal
            expressions.</p>
            <p>To see why, let’s consider rule 90 for each pattern.</p>
            <div class="float">
            <img src="/90r.png" alt="Rule 90 reversible"/>
            <div class="figcaption">Rule 90 reversible</div>
            </div>
            <table>
            <thead>
            <tr class="header">
            <th align="center">111</th>
            <th align="center">110</th>
            <th align="center">101</th>
            <th align="center">100</th>
            <th align="center">011</th>
            <th align="center">010</th>
            <th align="center">001</th>
            <th align="center">000</th>
            </tr>
            </thead>
            <tbody>
            <tr class="odd">
            <td align="center">0</td>
            <td align="center">1</td>
            <td align="center">0</td>
            <td align="center">1</td>
            <td align="center">1</td>
            <td align="center">0</td>
            <td align="center">1</td>
            <td align="center">0</td>
            </tr>
            </tbody>
            </table>
            <p><span class="math inline">01011010 = 90</span></p>
            <p>First for pattern <code>000</code>.</p>
            <div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1" tabindex="-1"/>  active <span class="op">&amp;</span> <span class="op">~(</span>left <span class="op">^</span> l<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span>center <span class="op">^</span> c<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span>right <span class="op">^</span> r<span class="op">);</span></span>
<span id="cb2-2"><a href="#cb2-2" tabindex="-1"/><span class="op">=</span> <span class="dv">0</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">0</span> <span class="op">^</span> l<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">0</span> <span class="op">^</span> c<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">0</span> <span class="op">^</span> r<span class="op">);</span></span>
<span id="cb2-3"><a href="#cb2-3" tabindex="-1"/><span class="op">=</span> <span class="fl">0.</span>`</span></code></pre></div>
            <p>Active is zero so the whole line reduces to zero. Now for
            <code>001</code>. Note that <code>1</code> here actually
            means <code>~0UL</code>, that is 64bit integer max.</p>
            <div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" tabindex="-1"/>   <span class="dv">1</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">0</span> <span class="op">^</span> l<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">0</span> <span class="op">^</span> c<span class="op">)</span> <span class="op">&amp;</span> <span class="op">~(</span><span class="dv">1</span> <span class="op">^</span> r<span class="op">);</span></span>
<span id="cb3-2"><a href="#cb3-2" tabindex="-1"/><span class="op">=</span> <span class="op">~</span>l <span class="op">&amp;</span> <span class="op">~</span>c <span class="op">&amp;</span> r<span class="op">.</span></span></code></pre></div>
            <p>As expected pattern <code>001</code> matches
            <code>l=0, c=0, r=1</code>. Let’s just list the remaining
            patterns or’ed together in their reduced state. Then reduce
            that further. Note that the <code>for</code> loop in
            <code>ca1d_rule_apply</code> will be <em>unrolled</em> by
            the compiler when optimising for performance. It’s also
            quite clear that <code>c_next_step</code> is dependant on an
            expression from the previous iteration or zero. So all the
            pattern match results will get or’ed together.</p>
            <div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1" tabindex="-1"/>  l <span class="op">&amp;</span> c <span class="op">&amp;</span> <span class="op">~</span>r <span class="op">|</span> l <span class="op">&amp;</span> <span class="op">~</span>c <span class="op">&amp;</span> <span class="op">~</span>r <span class="op">|</span> <span class="op">~</span>l <span class="op">&amp;</span> c <span class="op">&amp;</span> r <span class="op">|</span> <span class="op">~</span>l <span class="op">&amp;</span> <span class="op">~</span>c <span class="op">&amp;</span> r<span class="op">;</span></span>
<span id="cb4-2"><a href="#cb4-2" tabindex="-1"/><span class="op">=</span> l <span class="op">&amp;</span> <span class="op">~</span>r <span class="op">|</span> <span class="op">~</span>l <span class="op">&amp;</span> r<span class="op">;</span></span>
<span id="cb4-3"><a href="#cb4-3" tabindex="-1"/><span class="op">=</span> l <span class="op">^</span> r<span class="op">.</span></span></code></pre></div>
            <p>See on the top row that
            <code>(l &amp; c &amp; ~r | l &amp; ~c &amp; ~r)</code> or’s
            together <code>c</code> and not <code>c</code>. So we can
            remove it. Then we get an expression equivalent to xor’ring
            <code>l</code> and <code>r</code>.</p>
            <p>In theory at least, the compiler can see that
            <code>rule</code> only has 256 values and create a reduced
            version of <code>ca1d_rule_apply</code> for each value.
            Whether it actually does is not of much practical concern
            when the rendering code is the bottle neck. However it’s
            interesting to see if the compiler can deduce the best
            solution or whether anything trips it up.</p>
            <p>Judging from the disassembly from
            <code>gcc -O3 -mcpu=native -mtune=native</code>, it may
            actually do this. Additionally it <em>vectorizes</em> the
            code packing four 64bit ints at a time into 256bit registers
            and operating on those. I don’t know which part of the code
            it is vectorising or how. It’s possible that what I think is
            the rule being reduced is something related to
            vectorisation.</p>
            <div class="float">
            <img src="/210.png" alt="Rule 210"/>
            <div class="figcaption">Rule 210</div>
            </div>
            <p>To render the automata we take the approach of iterating
            over each pixel in the image. We calculate which cell the
            pixel falls inside and set the color of the pixel to that of
            the cell. That’s it.</p>
            <div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1" tabindex="-1"/><span class="co">/* Draws a pixel */</span></span>
<span id="cb5-2"><a href="#cb5-2" tabindex="-1"/><span class="dt">static</span> <span class="kw">inline</span> <span class="dt">void</span> shade_pixel<span class="op">(</span>gp_pixmap <span class="op">*</span>p<span class="op">,</span> gp_coord x<span class="op">,</span> gp_coord y<span class="op">,</span></span>
<span id="cb5-3"><a href="#cb5-3" tabindex="-1"/>                               gp_pixel bg<span class="op">,</span> gp_pixel fg<span class="op">)</span></span>
<span id="cb5-4"><a href="#cb5-4" tabindex="-1"/><span class="op">{</span></span>
<span id="cb5-5"><a href="#cb5-5" tabindex="-1"/>    gp_pixel px<span class="op">;</span></span>
<span id="cb5-6"><a href="#cb5-6" tabindex="-1"/>    <span class="dt">size_t</span> i <span class="op">=</span> <span class="op">(</span>x <span class="op">*</span> <span class="op">(</span><span class="dv">64</span> <span class="op">*</span> width<span class="op">))</span> <span class="op">/</span> p<span class="op">-&gt;</span>w<span class="op">;</span></span>
<span id="cb5-7"><a href="#cb5-7" tabindex="-1"/>    <span class="dt">size_t</span> j <span class="op">=</span> <span class="op">(</span>y <span class="op">*</span> height<span class="op">)</span> <span class="op">/</span> p<span class="op">-&gt;</span>h<span class="op">;</span></span>
<span id="cb5-8"><a href="#cb5-8" tabindex="-1"/>    <span class="dt">size_t</span> k <span class="op">=</span> <span class="dv">63</span> <span class="op">-</span> <span class="op">(</span>i <span class="op">&amp;</span> <span class="dv">63</span><span class="op">);</span></span>
<span id="cb5-9"><a href="#cb5-9" tabindex="-1"/>    <span class="dt">uint64_t</span> c <span class="op">=</span> steps<span class="op">[</span>gp_matrix_idx<span class="op">(</span>width<span class="op">,</span> j<span class="op">,</span> i <span class="op">&gt;&gt;</span> <span class="dv">6</span><span class="op">)];</span></span>
<span id="cb5-10"><a href="#cb5-10" tabindex="-1"/></span>
<span id="cb5-11"><a href="#cb5-11" tabindex="-1"/>    c <span class="op">=</span> BIT_TO_MAX<span class="op">(</span>c<span class="op">,</span> k<span class="op">);</span></span>
<span id="cb5-12"><a href="#cb5-12" tabindex="-1"/>    px <span class="op">=</span> <span class="op">(</span>fg <span class="op">&amp;</span> c<span class="op">)</span> <span class="op">|</span> <span class="op">(</span>bg <span class="op">&amp;</span> <span class="op">~</span>c<span class="op">);</span></span>
<span id="cb5-13"><a href="#cb5-13" tabindex="-1"/></span>
<span id="cb5-14"><a href="#cb5-14" tabindex="-1"/>    gp_putpixel_raw<span class="op">(</span>p<span class="op">,</span> x<span class="op">,</span> y<span class="op">,</span> px<span class="op">);</span></span>
<span id="cb5-15"><a href="#cb5-15" tabindex="-1"/><span class="op">}</span></span></code></pre></div>
            <p>GFXPrim makes drawing very simple. The above code is fast
            enough for my purpsoses, but a significant improvement can
            be had. Integer division is much slower than floating point
            multiplication on most newer CPUs. It’s actually much faster
            (2x at least) on my CPU to calculate a pair of ratios in
            floating point, then convert them back to integers.</p>
            <p>However, you may ask why we are even drawing on the CPU
            in the first place? This is because GFXPrim targets embedded
            systems with no graphics processor. Additionally the CPU may
            not even support floating point natively. So integer
            division may actually be faster in this case. Still better
            would be to limit the size of the pixmap to be <span class="math inline">2<sup><em>x</em></sup></span> larger
            than the dimensions of the automata, where <span class="math inline"><em>x</em> ∈ ℕ</span> then we can use
            shifts instead of division.</p>
            <div class="float">
            <img src="/210r.png" alt="Rule 210 Reversible"/>
            <div class="figcaption">Rule 210 Reversible</div>
            </div>
            <div class="float">
            <img src="/105r.png" alt="Rule 105 Reversible"/>
            <div class="figcaption">Rule 105 Reversible</div>
            </div>
            <div class="footnotes footnotes-end-of-document">
            <hr/>
            <ol>
            <li id="fn1"><p>In fact on my CPU it is 256 cells at a time.
            As AVX can be used to operate on 4 64bit words at a time.<a href="#fnref1" class="footnote-back">↩︎</a></p></li>
            <li id="fn2"><p>We perform a rotating shift which moves the
            end bit to the start. This causes the automata to wrap
            around.<a href="#fnref2" class="footnote-back">↩︎</a></p></li>
            <li id="fn3"><p>Combined with exclusive <em>or</em>.<a href="#fnref3" class="footnote-back">↩︎</a></p></li>
            <li id="fn4"><p>Or we can use xor as the patterns are
            mutually exclusive, so only one may match at a time for each
            bit.<a href="#fnref4" class="footnote-back">↩︎</a></p></li>
            <li id="fn5"><p>That’s me being an arse not Wolfram. Of
            course whenever “obvious” is used in these contexts it’s
            never really correct.<a href="#fnref5" class="footnote-back">↩︎</a></p></li>
            </ol>
            </div>
    </div>
  


guid: tag:world.hey.com,2005:World::Post/39378
title: Why don't more people use Linux?
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/why-don-t-more-people-use-linux-33b75f53
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>A couple of weeks ago, I <a href="https://x.com/yacineMTB/status/1825361755133952326">saw a tweet</a> asking: &quot;If Linux is so good, why aren&#39;t more people using it?&quot; And it&#39;s a fair question! It intuitively rings true until you give it a moment&#39;s consideration. Linux is even free, so what&#39;s stopping mass adoption, if it&#39;s actually better? My response:<br><br></div><blockquote><em>If exercising is so healthy, why don&#39;t more people do it?<br>If reading is so educational, why don&#39;t more people do it?<br>If junk food is so bad for you, why do so many people eat it?</em></blockquote><div><br>The world is full of free invitations to self-improvement that are ignored by most people most of the time. Putting it crudely, it&#39;s easier to be fat and ignorant in a world of cheap, empty calories than it is to be fit and informed. It&#39;s hard to resist the temptation of minimal effort.<br><br></div><div>And Linux isn&#39;t minimal effort. It&#39;s an operating system that demands more of you than does the commercial offerings from Microsoft and Apple. Thus, it serves as a dojo for understanding computers better. With a sensei who keeps demanding you figure problems out on your own in order to learn and level up.</div><div><br>Now I totally understand why most computer users aren&#39;t interested in an intellectual workout when all they want to do is browse the web or use an app. They&#39;re not looking to become a black belt in computing fundamentals.</div><div><br>But programmers are different. Or ought to be different. They&#39;re like firefighters. Fitness isn&#39;t the purpose of firefighting, but a prerequisite. You&#39;re a better firefighter when you have the stamina and strength to carry people out of a burning building on your shoulders than if you do not. So most firefighters work to be fit in order to serve that mission.</div><div><br>That&#39;s why I&#39;d love to see more developers <a href="https://omakub.org/">take another look at Linux</a>. Such that they may develop better proficiency in the basic katas of the internet. Such that they aren&#39;t scared to connect a computer to the internet without the cover of a cloud.</div><div><br>Besides, if you&#39;re able to figure out how to setup a modern build pipeline for JavaScript or even correctly configure IAM for AWS, you already have all the stamina you need for the Linux journey. Think about giving it another try. Not because it is easy, but because it is worth it.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39429
title: Optimize for bio cores first, silicon cores second
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/optimize-for-bio-cores-first-silicon-cores-second-112a6c3f
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>A big part of the reason that companies are going ga-ga over AI right now is the promise that it might materially lower their payroll for programmers. If a company currently needs 10 programmers to do a job, each have a cost of $200,000/year, then that&#39;s a $2m/year problem. If AI could even cut off 1/4 of that, they would have saved half a million! Cut double that, and it&#39;s a million. Efficiency gains add up quick on the bottom line when it comes to programmers!</div><div><br>That&#39;s why I love Ruby! That&#39;s why I work on Rails! For twenty years, it&#39;s been clear to me that this is where the puck was going. Programmers continuing to become more expensive, computers continuing to become less so. Therefore, the smart bet was on making those programmers more productive EVEN AT THE EXPENSE OF THE COMPUTER!</div><div><br>That&#39;s what so many programmers have a difficult time internalizing. They are in effect very expensive biological computing cores, and the real scarce resource. Silicon computing cores are far more plentiful, and their cost keeps going down. So as every year passes, it becomes an even better deal trading compute time for programmer productivity. AI is one way of doing that, but it&#39;s also what tools like Ruby on Rails were about since the start.</div><div><br>Let&#39;s return to that $200,000/year programmer. You can rent 1 AMD EPYC core from Hetzner for $55/year (they sell them in bulk, $220/month for a box of 48, so 220 x 12 / 48 = 55). That means the price of one biological core is the same as the price of 3663 silicon cores. Meaning that if you manage to make the bio core 10% more efficient, you will have saved the equivalent cost of 366 silicon cores. Make the bio core a quarter more efficient, and you&#39;ll have saved nearly ONE THOUSAND silicon cores!</div><div><br>But many of these squishy, biological programming cores have a distinctly human sympathy for their silicon counterparts that overrides the math. They simply feel bad asking the silicon to do more work, if they could spend more of their own time to reduce the load by using less efficient for them / more efficient for silicon tools and techniques. For some, it seems to be damn near a moral duty to relieve the silicon of as many burdens they might believe they&#39;re able carry instead.<br><br></div><div>And I actually respect that from an artsy, spiritual perspective! There <em>is</em> something beautifully wholesome about making computers do more with fewer resources. I still look oh-so-fondly back on the demo days of the Commodore 64 and Amiga. What those wizards were able to squeeze out of <a href="https://www.youtube.com/watch?v=wl6mXn_wHEw">a mere 4kb</a> to make the computer dance in sound and picture was truly incredible.</div><div><br>It just doesn&#39;t make much economic sense, most of the time. Sure, there&#39;s still work at the vanguard of the computing threshold. Somebody&#39;s gotta squeeze the last drop of performance out of that NVIDIA 4090, such that our 3D engines can raytrace at 4K and 120FPS. But that&#39;s not the reality at most software businesses that are in the business of making business software (say that three times fast!). Computers have long since been way fast enough for that work to happen without heroic optimization efforts.</div><div><br>And that&#39;s the kind of work I&#39;ve been doing for said twenty years! Making business software and selling it as SaaS. That&#39;s what an entire industry has been doing to tremendous profit and gainful employment across the land. It&#39;s been a bull run for the ages, and it&#39;s been mostly driven by programmers working in high-level languages figuring out business logic and finding product-market fit.<br><br></div><div>So whenever you hear a discussion about computing efficiency, you should always have the squishy, biological cores in mind. Most software around the world is priced on their inputs, not on the silicon it requires. Meaning even small incremental improvements to bio core productivity is worth large additional expenditures on silicon chips. And every year, the ratio grows greater in favor of the bio cores.</div><div><br>At least up until the point that we make them obsolete and welcome our AGI overlords! But nobody seems to know when or if that&#39;s going to happen, so best you deal in the economics of the present day, pick the most productive tool chain available to you, and bet that happy programmers will be the best bang for your buck.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39473
title: Passwords have problems, but passkeys have more
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/passwords-have-problems-but-passkeys-have-more-95285df9
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>We had originally planned to go all-in on passkeys for <a href="https://once.com/campfire">ONCE/Campfire</a>, and we built the early authentication system entirely around that. It was not a simple setup! Handling passkeys properly is surprisingly complicated on the backend, but we got it done. Unfortunately, the user experience kinda sucked, so we ended up ripping it all out again.<br><br></div><div>The problem with passkeys is that they&#39;re essentially a halfway house to a password manager, but tied to a specific platform in ways that aren&#39;t obvious to a user at all, and liable to easily leave them unable to access of their accounts. Much the same way that two-factor authentication can do, but worse, since you&#39;re not even aware of it.<br><br></div><div>Let&#39;s take a simple example. You have an iPhone and a Windows computer. Chrome on Windows stores your passkeys in Windows Hello, so if you sign up for a service on Windows, and you then want to access it on iPhone, you&#39;re going to be stuck (unless you&#39;re so forward thinking as to add a second passkey, somehow, from the iPhone will on the Windows computer!). The passkey lives on the wrong device, if you&#39;re away from the computer and want to login, and it&#39;s not at all obvious to most users how they might fix that.</div><div><br>Even in the best case scenario, where you&#39;re using an iPhone and a Mac that are synced with Keychain Access via iCloud, you&#39;re still going to be stuck, if you need to access a service on a friend&#39;s computer in a pinch. Or if you&#39;re not using Keychain Access at all. There are plenty of pitfalls all over the flow. And the solutions, like scanning a QR code with a separate device, are cumbersome and alien to most users.<br><br></div><div>If you&#39;re going to teach someone how to deal with all of this, and all the potential pitfalls that might lock them out of your service, you almost might as well teach them how to use a cross-platform password manager like 1password.</div><div><br>Yes, passwords have problems. If you&#39;re using them without a password manager, you&#39;re likely to reuse them across multiple services, and if you do, all it takes is one service with awful password practices (like storing them in plain text rather than hashing them with something like bcrypt), and a breach will mean hackers might get access to all your other services.</div><div><br>But just because we have a real problem doesn&#39;t mean that all proposed solutions are actually going to be better. And at the moment, I don&#39;t see how passkeys are actually better, and, worse still, can become better. Unless you accept the idea that all your passwords should be tied to one computing ecosystem, and thus make it hard to use alternative computers.</div><div><br>A decent alternative to passkeys, if you need the extra layer of security, is to lean on email for the first login from a new device. Treating email as a second factor, but only on the first login from that device. Everyone has email, everyone understands email. (Just don&#39;t force us all to go through magic links exclusively, as that&#39;s a pain too for those who&#39;ve actually adopted a password manager!).</div><div><br>Bottom line, I&#39;m disappointed to report that passkeys don&#39;t appear worth the complexity of implementation (which is substantial!) nor the complexity and gotchas of the user experience. So we&#39;re sticking to passwords and emails. Encouraging opt-in 2FA and password managers, but not requiring them.<br><br>Passkeys seemed promising, but not all good intentions result in good solutions.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39478
title: Back in the market (Sonos Edition)
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/back-in-the-market-sonos-edition-b8b3c0b2
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I&#39;ve been a Sonos megafan for years. Owned probably two dozen devices for different homes. Mainly amps for in-ceiling speakers, but also some Ones, 3s, 5s. All of it. Because it Just Worked when it came to multi-room music. Now it doesn&#39;t, and it hasn&#39;t for a long time, so I&#39;ve been back in the market.<br><br>I&#39;m not exactly sure what the problem is. The new app has <a href="https://www.engadget.com/audio/speakers/why-is-the-sonos-app-so-broken-140028060.html">gotten a lot of the blame</a> for Sonos&#39; problems, but to me, the bigger issue has been how unreliable the system at large has become. And that doesn&#39;t seem like it&#39;s just an app issue. Probably more of a firmware problem. But whatever it is, it&#39;s been driving me crazy.<br><br>When you want to listen to some music at dinner, you want play to mean PLAY RIGHT NOW. Not &quot;won&#39;t connect&quot;. Not &quot;try restarting the app&quot;. Just play. But Sonos hasn&#39;t been like that. It&#39;s been an exercise in frustration instead.<br><br>I sympathize with their situation, though. <a href="https://world.hey.com/dhh/software-has-bugs-this-is-normal-26d5fd06">Software is hard!</a> Especially when you&#39;ve been around as long as Sonos has, and have a back catalog of a million different devices, as well as a road map with tons of new stuff coming out. It can&#39;t be easy to juggle all that.<br><br>The second thing that&#39;s clearly hard is wireless synchronization. Sonos has a huge patent portfolio for making sure the music is always in sync across multiple rooms and devices, even when it&#39;s running over a wireless connection. <a href="https://arstechnica.com/gadgets/2022/01/google-loses-sonos-patent-case-starts-stripping-functionality-from-speakers/">Google lost in court</a> when they tried to steal that tech. It&#39;s a formidable fortress.<br><br>But I don&#39;t need wireless. All my gear is hardwired with ethernet. And that&#39;s why the problems I&#39;ve had have been extra infuriating. When the music drops out. Or it won&#39;t start. Or you can&#39;t connect to the devices. That just shouldn&#39;t happen when it&#39;s on a hardwired connection, but it does.<br><br>And it&#39;s not like we haven&#39;t tried to figure this out. It&#39;s literally been months of debugging. The AV outfit I&#39;m using has been working with Sonos support. They&#39;ve been replacing Amps with newer hardware. Lots of experimentation. But nothing has made the system reliable or enjoyable to use. Certainly not through the Sonos app.<br><br>So last week I finally threw in the towel and got back into the market. Turns out there are quite a few competitors out there now. I decided to try two: <a href="https://www.bluesound.com/products/powernode-edge/">Bluesound</a> and <a href="https://www.wiimhome.com/wiimamp/overview">WiiM</a>. They offer a comparable streaming amp that I can hook up to my in-ceiling Klipsch speakers, and they both connect via ethernet, and they both support <a href="https://support.spotify.com/us/article/spotify-connect/">Spotify Connect</a>. WiiM in particular has been <a href="https://www.youtube.com/watch?v=hyGSWFYFuqk">wowing hifi aficionados</a> with their incredible price/performance ratio. <br><br>Instantly it was revelation. Music to either amp would start <em>immediately</em> when I selected a song in Spotify. I&#39;d been boiled by the Sonos problems for so long that I didn&#39;t even remember what <em>instant</em> does for enjoyment. It does a lot!<br><br>And now that I&#39;ve been pushed back into the market, I&#39;ve realized that the historic Sonos app advantage just doesn&#39;t matter nearly as much as it used to. The Spotify app is a superior way to browse music, and both WiiM and Bluesound make it easy to group speakers. In the past, those two points served as the Sonos moat. That&#39;s over, it seems.<br><br>Further more, the WiiM Amp is just $299! That&#39;s half the price of the Sonos Amp (and the Bluesound). And for the kind of in-ceiling, background music I&#39;m using it for, it&#39;s more than plenty. And despite the low price, the software is actually the best of all three options. It&#39;s incredibly easy and quick to set up. You&#39;re playing music five minutes after you&#39;ve unpacked the device.<br><br>I&#39;m telling you all of this because there are a lot of lessons for business owners of all types in this Sonos predicament. Like, if you&#39;ve managed to win over a customer, the last thing you want to do is get them back into the market to sample the competition. If you can keep them content with what they got, they aren&#39;t interested in whatever anyone else is offering.<br><br>That&#39;s why it&#39;s worth going the extra effort not to fuck with existing customers. <a href="https://businessofsoftware.org/2015/10/david-heinemeier-hansson-rewrite-basecamp-business-of-software-conference-video-dhh-bos2015/">That&#39;s why we run three different versions of Basecamp</a>. Including one that hasn&#39;t seen any feature updates for 14 years! A version that still has thousands of happy customers generating millions in revenue every year. They signed up for a system they liked in the mid-to-late 2000s, and they&#39;re not in the market for a change. THAT&#39;S JUST FINE BY US!<br><br>Again, it isn&#39;t free to do this. But Sonos eventually got it right the <a href="https://www.gearbrain.com/old-sono-stop-software-updates-2644889020.html">last time they faced this dilemma</a>. When they wanted to push the last new Sonos app, and couldn&#39;t make their plans work with the old hardware. The first approach would have essentially bricked them all. But they came around, split the apps, and I still use the Sonos S1 setup with an installation that&#39;s over a decade old.<br><br>And I&#39;m sure we&#39;ve gotten it wrong at <a href="https://37signals.com/">37signals</a> many times over the years too. Accidentally changed something that we thought would be better, or at least more attractive to new customers, and ended up pushing happy buyers back into the market. Some of that is unavoidable, but a lot of it is not. A lot of it is a choice.<br><br>Don&#39;t make that choice. Don&#39;t push customers back into the market. They might just find that Spotify Connect is pretty awesome, and that amps half the price can do the job. Keep current customers happy, then go chasing new ones.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39560
title: Wonderful vi
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/wonderful-vi-a1d034d3
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>The speed of change in technology often appears to be the industry&#39;s defining characteristic. Nothing highlights that perception more than the recent and relentless march of AI advancements. But for as much as some things in technology change, many other things stay the same. Like vi!</div><div><br>vi is a programming text editor that was created by Bill Joy before computers even had real graphical interfaces, <a href="https://en.wikipedia.org/wiki/Vi_(text_editor)">back in 1976</a>. Just five years after the first microprocessor, the Intel 4004. In computing terms, we might as well be talking about ancient Egyptian hieroglyphs here. It&#39;s that old.</div><div><br>But it&#39;s fundamental design, splitting insert mode from command mode, remains unchanged in its modern successors, like <a href="https://www.vim.org/">Vim</a> and <a href="https://neovim.io/">Neovim</a>. In fact, the entire vi ethos of maximizing programmer productivity by minimizing keystrokes has carried forward all these years with remarkably little distortion. In 1976, most computers didn&#39;t even have a mouse. In 2024, most vi-successor users don&#39;t even need one when programming. </div><div><br>That&#39;s kinda incredible! That I can sit here, almost half a century after Bill Joy first gave birth to vi, and enjoy the same quirky style of text editing to make modern web apps in 2024. It&#39;s not <em>why</em> I use Neovim, but it sure does make it feel extra special.</div><div><br>The other reason it feels special is that vi makes turns manipulating text into a key-based form of Street Fighter. Sure, you can have fun just learning the basic buttons for punching and kicking, but the game unlocks an entirely new dimension the moment you pull off <a href="https://www.youtube.com/watch?v=3ihrSG0j6l0">your first hadoken</a> — a fireball move done by making a half circle with the joystick followed by a punch. And now you&#39;re off to learn all the special moves followed by techniques for stringing them together into combos.<br><br></div><div>That&#39;s what pulling a &quot;ciq&quot; in Neovim feels like. It stands for &quot;Change Inside Quotes&quot;. So say you&#39;re in the middle of a line of code like this: &quot;puts &#39;Hello&lt;cursor&gt; World&#39;&quot;. With that cursor placed after the &quot;Hello&quot;, the &quot;ciq&quot; move will select all the text inside the quotes (&quot;Hello World&quot;), remove it, and place your cursor right after the opening quotes, ready to write something new. That&#39;s pretty magic!</div><div><br>And it just goes on and on from there. You can use &quot;dab&quot; to &quot;Delete Around Brackets&quot;, which is great when you want to remove all the parameters used for a method at the end of a line in Ruby. Or what about &quot;vii&quot; to &quot;(Visually) Select Inside [the current level of] Indention&quot;, so you have the entire body of a method highlighted, ready for overwriting with a paste or copying or cutting. Or just &quot;yiw&quot; which copies the current word your cursor is on, regardless of where in the word it is, and copies it to the clipboard.</div><div><br>There&#39;s an astounding number of combos like these available in Neovim (and the other vi flavors). But now you&#39;re probably thinking: how could anyone possibly remember all that? Which brings me to the real wonder of vi: It&#39;s not just an editor, it&#39;s a <em>language</em> for editing. Once you learn the basic grammar of vi text manipulation, and you learn a few actions, scopes, and objects, you can string it all together in any combination possible.<br><br></div><div>Here&#39;s the structure: [Action] [Scope] [Object]. I&#39;ve already given you four actions in the examples above: change, select, delete, and copy. And there are only two primary scopes: inside and around. And we&#39;ve looked at four different objects: quotes, brackets, indention, and word. There&#39;s your language.<br><br></div><pre>yaq = Copy (yank) Around Quotes<br>diw = Delete Inside Word<br>vab = Select (visually) Around Brackets</pre><div><br>See how it&#39;s starting to make sense? Now let&#39;s add one more move to the combo, which is a count. So you can also do:<br><br></div><pre>3cw = Change Three Words
4dd = Delete Four Lines
10j = Jump Ten Lines</pre><div><br></div><div>There&#39;s more to learning the vi command mode than just this, but to me, this is where the magic is. The language of text manipulation. The action-scope-object grammar. It&#39;s when that clicks that the combo stringing begins, and your dopamine starts flowing.</div><div><br>It&#39;s just uniquely satisfying to string a handful of these combos together and see the text beneath you radically manipulated. In a way you just know would have been a drag to do in any other editor. That&#39;s the game-like joy of vi&#39;s power moves.</div><div><br>Now all of this still comes with quite some learning curve, of course. On top of the text manipulation, there&#39;s a bunch of <a href="https://manual.omakub.org/1/read/13/neovim">basic navigation keystrokes</a> to learn, but I think you ought to start with the basic grammar explained above. That&#39;s the fun bit, that&#39;s the addictive bit.</div><div><br>And if this appetizer has you hungry for more, I&#39;d start by installing Neovim using <a href="https://www.lazyvim.org/">the superb LazyVim distribution</a>. Neovim from scratch is like climbing Mount Everest without oxygen. If all you&#39;re interested in at first is a peek at the view, book that LazyVim helicopter tour before bothering the sherpas. Then checkout the excellent Vim and Neovim tutorials available on Youtube from the likes of <a href="https://www.youtube.com/watch?v=X6AR2RMB5tE&amp;list=PLm323Lc7iSW_wuxqmKx_xxNtJC_hJbQ7R">ThePrimeagan</a> and <a href="https://www.youtube.com/watch?v=zHTeCSVAFNY&amp;list=PLsz00TDipIffreIaUNk64KxTIkQaGguqn">Typecraft</a>, along with <a href="https://www.youtube.com/watch?v=N93cTbtLCIM">Elijah Manor&#39;s LazyVim introduction</a>.<br><br></div><div>You can run Neovim on any operating system, but it works better if you&#39;re using a modern, fast terminal like <a href="https://alacritty.org/">Alacritty</a> or Kitty. I personally use Alacritty and Neovim together with the multi-pane terminal enhancement <a href="https://zellij.dev/">Zellij</a>. The entire package is configured out of the box in <a href="https://omakub.org/">Omakub</a>, if your adventurous spirit should extend to a trip into Linux. But you absolutely don&#39;t need to run Linux to enjoy Neovim. It&#39;s great on both Mac and Windows too.<br><br></div><div>So that&#39;s it. That&#39;s my testimony to what a wonderful experience it&#39;s been adopting Neovim. It certainly wasn&#39;t without some frustration (like figuring out how to do my own snippets!!), and it&#39;s not without some sadness that I&#39;ve given up on my beloved TextMate editor, but I can comfortably say, <a href="https://world.hey.com/dhh/finding-the-last-editor-dae701cc">after running this stack since February</a>, that it feels like home now. A combo-smashing, hadoken-wielding home. And it&#39;s awesome.</div><div><br>May vi reign for another fifty years and beyond!</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39584
title: Ears rarely open until a rapport is established
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/ears-rarely-open-until-a-rapport-is-established-ae913bfd
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>It&#39;s hard to open cold with a controversial take to a bunch of strangers. And the room is always cold on X or in a one-off blog post. Just like comedy, half the battle of winning over the audience comes from a solid introduction, good timing, and a broad smile to warm the room. You can have great material, but if the vibe is off, good luck landing a laugh.</div><div><br><a href="https://www.youtube.com/watch?v=mTa2d3OLXhg">The stream I did on Monday</a> with ThePrimeagen and TJ DeVries illustrates this to a T. Not only was the stream warm and in a good mood from spending time with ThePrimeagen first (who wouldn&#39;t be!), but the pair immediately elevated that spirit further by being such welcoming and gracious hosts. Thereby signaling to their audience that who they were about to hear would be worth listening to with an open mind.</div><div><br>That&#39;s the kind of introduction that makes all the difference as to whether someone is willing to grant you the grace of charitable listening -- or whether they&#39;ll immediately set their defenses to Max Stranger Skepticism.</div><div><br>I&#39;ve been making many of my main arguments for years. Some for decades, even. And I know that many in that stream had probably heard some of them before, and dismissed them out of hand, because we hadn&#39;t established a rapport that would warrant an open mind. <br><br></div><div>That&#39;s where writing just can&#39;t compete with a podcast or a stream. Putting a face, a voice, and a vibe to the argument absolutely changes its tone, and in turn, the emotions it evokes. And that&#39;s what most people go off on. Those emotions.</div><div><br>I sometimes do struggle with that. Thinking that the strength of an argument should be gauged purely by its logic or at least its rhetoric. But I&#39;ve really come to appreciate the value of set and setting. Of a warm introduction. Of establishing a rapport.<br><br></div><div>We might not all become friends on the internet, but we needn&#39;t be strangers either. And the best way to move on from being strangers is by having others vouch for your earnestness. Thanks for doing that, ThePrimeagen and TJ DeVries ✌️</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39731
title: Wonderful Rails World Vibes
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/wonderful-rails-world-vibes-7a6141d2
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I totally understand how programming conferences end up being held in a drab Sheraton hotel somewhere to save money. It&#39;s expensive to outfit a cool venue with the gear and operations needed to pull off a great experience for speakers, sponsors, and attendees. And while the cost of doing something more inspiring than a carpet-clad conference hotel is clear, the pay off is often fuzzy until you do. But <a href="https://www.youtube.com/watch?v=PzsRWH0n6O4">Rails World 2024</a> in Toronto just made that value crystal clear. Holy smackeroli, what an incredible show!!<br><br></div><div class="attachment-gallery attachment-gallery--4">
    <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09272024-1094.jpg" title="Download RothMedia-09272024-1094.jpg" data-click-proxy-target="lightbox_link_blob_1830806437" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2VsNHg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--899301a42cd2f506e2e25ef863a220a12e2725ae/RothMedia-09272024-1094.jpg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1767.jpg" title="Download RothMedia-09262024_Web-1767.jpg" data-click-proxy-target="lightbox_link_blob_1830806438" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2VtNHg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--4e9a2369a3391889e6700c0c9df241bbe10a2b9c/RothMedia-09262024_Web-1767.jpg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1598.jpg" title="Download RothMedia-09262024_Web-1598.jpg" data-click-proxy-target="lightbox_link_blob_1830806441" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2VwNHg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--a932fa9328794971cfa4112f48c1d253f03c6678/RothMedia-09262024_Web-1598.jpg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1216.jpg" title="Download RothMedia-09262024_Web-1216.jpg" data-click-proxy-target="lightbox_link_blob_1830806440" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2VvNHg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--01884dcce0d1f8fdb48ad60f97c1a02a7dd15026/RothMedia-09262024_Web-1216.jpg?disposition=attachment">
</a>
  </figure>
</div><div>We had over a thousand people gathered from 57 countries in one of the coolest conference venues I&#39;ve ever had the pleasure of talking to programmers in. Amanda Perino, the executive director of the Rails Foundation, and the mastermind behind Rails World, gambled on an inside/outside venue in Toronto in September, and it paid off big. Talking Rails between the trees, in the open air, and basking in the sun made for a unique and mesmerizing couple of days in Canada.<br><br></div><div class="attachment-gallery attachment-gallery--2">
    <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1243.jpg" title="Download RothMedia-09262024_Web-1243.jpg" data-click-proxy-target="lightbox_link_blob_1830810260" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2VVOGg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--f312dd10be721555a2ad8d8a3e42e675cbea993c/RothMedia-09262024_Web-1243.jpg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1262.jpg" title="Download RothMedia-09262024_Web-1262.jpg" data-click-proxy-target="lightbox_link_blob_1830812879" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2ZQL0I5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--983ce8eb75f48977246f7638dae32c46c1754f41/RothMedia-09262024_Web-1262.jpg?disposition=attachment">
</a>
  </figure>
</div><div>The fact that we managed to time <a href="https://rubyonrails.org/2024/9/27/rails-8-beta1-no-paas-required">the first beta release of Rails 8</a> with the conference certainly helped too. The bold leap from #NOBUILD to #NOPAAS, the release of an entire trifecta of Solid adapters (powered by SQLite by default!), and <a href="https://dev.37signals.com/kamal-2/">the release of Kamal 2.0</a> (with it&#39;s brand new purpose-built proxy!) made for perhaps the most exciting shipping season in well over a decade for Rails.<br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--webp">
      <a download="no-pass-s.webp" title="Download no-pass-s.webp" data-click-proxy-target="lightbox_link_blob_1830795523" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2NEdVI5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--ff409501f861d597bbbe4540b3d131fe2230b3b0/no-pass-s.webp?disposition=attachment">
</a>
  </figure></div><div><br>It&#39;s clear that after spending a few years in the wilderness with webpacker and whatnot, Rails has found a new stride and a new confidence to pursue its counter melody to the rest of the industry. While everyone seems resigned to slice the expertise of web development into ever thinner specialties, Rails is doubling down on the one-developer framework, the full stack, and the compression of complexity.<br><br></div><div class="attachment-gallery attachment-gallery--2">
    <figure class="attachment attachment--preview attachment--lightboxable attachment--jpeg">
      <a download="progress-haiku.jpeg" title="Download progress-haiku.jpeg" data-click-proxy-target="lightbox_link_blob_1830778191" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RQZFI5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--2c8ea39a409ba5f77369bf69f38ba7f2921137d1/progress-haiku.jpeg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpeg">
      <a download="serverphobia.jpeg" title="Download serverphobia.jpeg" data-click-proxy-target="lightbox_link_blob_1830778185" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RKZFI5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--79e392f36843ded2c1dcbadbfb2dbe8b9d11618f/serverphobia.jpeg?disposition=attachment">
</a>
  </figure>
</div><div>And while venture capitalists are moving in on developer tech from all sides, Rails is reaffirming its commitment to open source generics, and deployment strategies that don&#39;t require paying big premiums for wrappers around AWS. (You should never need a PaaS subscription to go live with Rails!).<br><br></div><div>But while both of those ingredients, a fantastic venue and a stacked shipping schedule, helped set us up for a good time, the fact that THE VIBES have so definitively turned around in the Rails ecosystem, as well as the rest of the programming world, certainly contributed too. We&#39;ve now long since put those awkward first years of the decade behind us, and we&#39;re just back to having a great time celebrating competency and conceptual compression together.<br><br></div><div>And what a celebration! While I really enjoyed delivering <a href="https://www.youtube.com/watch?v=-cEn_83zRFw">the opening keynote</a>, it was the session with Tobi and Matz that truly warmed my heart. I haven&#39;t had a chance to really talk with Matz for many years, to truly thank him for the incredible gift of Ruby that he just keeps delivering to us. So to do so in a session moderated by Tobi was beyond special. So too was offering Matz the Rails Lifetime Award, which apparently was the first award Matz has ever received himself. Just look at this:<br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpeg">
      <a download="matz-award.jpeg" title="Download matz-award.jpeg" data-click-proxy-target="lightbox_link_blob_1830774335" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2MvWmg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--9badfead56105b0f93db55fa271f4fde4540de8d/matz-award.jpeg?disposition=attachment">
</a>
  </figure></div><div><br>Last year&#39;s recipient, Tobi, also did his part and more to make us all feel incredibly welcome on Shopify&#39;s home turf of Toronto. From the pre-game event, to the support for the conference, to the insane after party. Shopify&#39;s patronage towards Ruby and Rails is the stuff of a living legend, and the results, from their superb work on YJIT, to their strong presence on Rails Core, to their support of the Rails Foundation and Rails World. We couldn&#39;t have asked for a better host or benefactor!<br><br></div><div class="attachment-gallery attachment-gallery--2">
    <figure class="attachment attachment--preview attachment--lightboxable attachment--jpeg">
      <a download="shopify-pregame-s.jpeg" title="Download shopify-pregame-s.jpeg" data-click-proxy-target="lightbox_link_blob_1830792044" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RzcXg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--515f7c4ad1eecfc755ee68fda8014633eef92d77/shopify-pregame-s.jpeg?disposition=attachment">
</a>
  </figure>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09262024_Web-1966.jpg" title="Download RothMedia-09262024_Web-1966.jpg" data-click-proxy-target="lightbox_link_blob_1830807405" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2R0NXg5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--39ddf1afd7b9306fd9ca577e4109dd41d6aebd00/RothMedia-09262024_Web-1966.jpg?disposition=attachment">
</a>
  </figure>
</div><div><br></div><div>Now I know all of this sounds a bit sappy at this point. Thanks going here, thanks going there, but that really is the key sentiment that I left Toronto with. Just an immense gratitude towards all the companies, contributors, and individuals working together in the Rails ecosystem for a better tomorrow. The web does not have to be as complicated as we&#39;ve let it become, and here&#39;s a corner of the programming world pushing back in unison.</div><div><br>I mean, I&#39;ve been working on <a href="https://x.com/dhh/status/1840499307579072514">The Web Problem</a> with Ruby through Rails for well over twenty years now, but I&#39;m as fired up as ever to push the frontier forward. And it&#39;s largely because the effort is sustained by such a broad and charitable ecosystem.</div><div><br>With Rails World such a roaring success -- I mean it <a href="https://x.com/dhh/status/1785368652440916121">sold out in a mere twenty minutes</a> and still managed to surpass the hype!! -- it might look obvious in retrospect that it was always going to be like this. But it wasn&#39;t obvious at all at the outset. It took a real leap of faith from <a href="https://cookpad.com/">Cookpad</a>, <a href="https://www.doximity.com/">Doximity</a>, <a href="https://www.fleetio.com/">Fleetio</a>, <a href="https://github.com/">GitHub</a>, <a href="https://www.intercom.com/">Intercom</a>, <a href="https://www.procore.com/">Procore</a>, and <a href="https://www.shopify.com/">Shopify</a> to join with <a href="https://37signals.com/">37signals</a> in creating <a href="https://rubyonrails.org/foundation">The Rails Foundation</a>, without which none of this would have happened.</div><div><br>The fact that we were able to put on this incredible celebration of Rails in Toronto at a very affordable entry price relied not just on the support of sponsors like <a href="https://shopify.com">Shopify</a>, <a href="https://github.com/">GitHub</a>, <a href="https://www.appsignal.com/">AppSignal</a>, <a href="https://www.clio.com/">Clio</a>, <a href="https://www.huntress.com/">Huntress</a>, <a href="https://valkey.io/">Valkey</a>, <a href="https://www.crunchydata.com/">crunchydata</a>, <a href="https://paraxial.io/">Paraxial.io</a>, <a href="https://sentry.io/">Sentry</a>, <a href="https://www.mongodb.com/">MongoDB</a>, <a href="https://www.happyscribe.com/">happyscribe</a>, <a href="https://frame.work/">framework</a>, <a href="https://rubyonrails.org/world/2024">and others</a>, but also on the fact that the Rails Foundation, the founding core members listed above, as well as the contributing members (AppSignal, <a href="https://www.bigbinary.com/">BigBinary</a>, <a href="https://www.cedarcode.com/">cedarcode</a>, <a href="https://makandra.de/en">makandra</a>, <a href="https://www.planetargon.com/">Planet Argon</a>, <a href="https://www.renuo.ch/">Renuo</a>, and <a href="https://www.tablecheck.com/">TableCheck</a>), were willing to happily underwrite a loss of over $100,000 on the conference itself.</div><div><br>Because the mission for The Rails Foundation is to broaden the appeal of Rails, excite existing and new programmers in our ecosystem, and help educate them all on the latest advances with the framework. That&#39;s what the budget is for, and spending a considerable chunk of it on subsidizing Rails World serves that mission in full.<br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="RothMedia-09272024-1018.jpg" title="Download RothMedia-09272024-1018.jpg" data-click-proxy-target="lightbox_link_blob_1830807870" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2MrNlI5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--d25d0d1b9a677919a6c1b08771ddfe95c69e3542/RothMedia-09272024-1018.jpg?disposition=attachment">
</a>
  </figure><br><br></div><div>In the coming days and weeks, we&#39;ll be releasing all the sessions from Rails World on <a href="https://www.youtube.com/@railsofficial">the Rails YouTube channel.</a> I know there was enough FOMO to float a blimp online from those who didn&#39;t manage to snatch a ticket in those ludicrously short twenty minutes it took before the conference sold out, but at least all the keynotes and sessions are made available as quickly as we can edit and upload them. You won&#39;t be getting the vibes of the hallway track, but maybe you&#39;ll have a chance to remedy that next year, when Rails World returns to Amsterdam for the 2025 show!</div><div><br>In the mean time, just one last thank you to everyone who attended, brought their good vibes, and helped ensure that we can all feel energized and inspired about Ruby on Rails for another year and beyond! ✌️❤️ <br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpeg">
      <a download="tenderlove-s.jpeg" title="Download tenderlove-s.jpeg" data-click-proxy-target="lightbox_link_blob_1830794164" href="https://world.hey.com/dhh/7a6141d2/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2Uwc3g5dCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--2065016232b2180396288a904d98ee4817482d80/tenderlove-s.jpeg?disposition=attachment">
</a>
  </figure></div>
</div>


guid: tag:world.hey.com,2005:World::Post/39776
title: Kamal 2: Thou need not PaaS
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/kamal-2-thou-need-not-paas-c9e8bd53
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div><a href="https://kamal-deploy.org/">Kamal</a> was our ticket out of the cloud. A simple tool for deploying containerized applications onto our own hardware, without the need for the complexity of something like Kubernetes. <a href="https://dev.37signals.com/kamal-2/">Kamal 2</a> is a huge leap forward for that tool, and it has just shipped. </div><div><br>Now you can deploy multiple applications to the same server, and you can have SSL certificates automatically provisioned via Let&#39;s Encrypt. A big compression in complexity, especially when just getting started.</div><div><br>Because Kamal isn&#39;t just for high-end cloud exits where applications rely on an entire fleet of machines. It&#39;s also an excellent option for running a bunch of smaller apps on a single server. Imagine just how you can run on <a href="https://www.hetzner.com/dedicated-rootserver/ax162-r/configurator/#/">one of those amazing Hetzner EPYC 9454 boxes</a> with 96 threads and 256GB of RAM that they sell for $220/month! </div><div><br><a href="https://basecamp.com/cloud-exit">Our move out of the cloud</a> would not has been nearly as smooth or as fast without Kamal. And I&#39;m thrilled we can share such a tool with everyone else who might want to reconsider the cost of Platform-as-a-Service setups. Kamal works great whether you&#39;re starting on a cheap $5 VPS, moving onto a fleet of cloud VMs, using dedicated-but-managed servers, or running your own hardware entirely.</div><div><br>In fact, it&#39;s chief mission is to allow you to move through all those stages of a production deployment without onerous migration costs or delays. We can&#39;t have competition in the cloud as long as folks are locked into proprietary or overly-complicated setups that makes moving from one vendor to another a huge hassle and expense.</div><div><br>If this sounds at all appetizing, <a href="https://www.youtube.com/watch?v=QC4b2teG_hc">checkout the new Kamal 2 demo</a>, which shows how to deploy a simple Go application (Kamal isn&#39;t just for Rails!), how to add another Rails app on the same box, and how to move that Rails app onto a three-machine Hetzner cloud setup. All in under half an hour.</div><div><br>Enjoy Kamal 2!<br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--webp">
      <a download="kamal-demo.webp" title="Download kamal-demo.webp" data-click-proxy-target="lightbox_link_blob_1835682903" href="https://world.hey.com/dhh/c9e8bd53/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RYVEdwdCIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--c640f4b4f743787c119a073886a047ac655f6c2e/kamal-demo.webp?disposition=attachment">
</a>
  </figure></div>
</div>


guid: tag:world.hey.com,2005:World::Post/39853
title: Automattic is doing open source dirty
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/automattic-is-doing-open-source-dirty-b95cf128
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div><a href="https://www.cnbc.com/2024/10/05/wordpress-ceo-matt-mullenweg-goes-nuclear-on-silver-lake-wp-engine-.html">Automattic demanding 8% of WP Engine&#39;s revenues</a> because they&#39;re not &quot;giving back enough&quot; to WordPress is a wanton violation of general open source ideals and the specifics of <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html">the GPL license</a>. Automattic is completely out of line, and the potential damage to the open source world extends far beyond the WordPress. Don&#39;t let <a href="https://techcrunch.com/2024/10/04/159-employees-are-leaving-automattic-as-ceos-fight-with-wp-engine-escalates/">the drama</a> or its characters distract you from that threat.<br><br></div><div>A key part of why open source has been so successful over the last several decades is the clarity and certainty of its licensing regime. Which allow you to build a business on open source without fear of frivolous claims or surprise shakedowns. The terms of the deal are spelled out in the license agreement, and the common ones, like MIT, BSD, or GPL, have all stood the test of time.</div><div><br>The most important part of such a license is usually the fact that the software is offered without any warranty. But some also include provisions that require any modifications to be released as open source as well. None of the major licenses, however, say anything close to &quot;it&#39;s free but only until the project owners deem you too successful and then you&#39;ll have to pay 8% of your revenues to support the project&quot;. That&#39;s a completely bonkers and arbitrary standard based in the rule of spite, not law.<br><br></div><div>I don&#39;t even have a dog in this fight, only a set of principles. If anything, I&#39;d be naturally inclined to be on Team WordPress. Between creating one of the most widely used open-source programs and powering half the internet, there&#39;s every tribal reason to side with Automattic over WP Engine&#39;s private-equity owners at Silver Lake.<br><br></div><div>But whatever my feelings about private equity in general or Silver Lake&#39;s management of WP Engine in particular, I care far more about the integrity of open source licenses, and that integrity is under direct assault by Automattic&#39;s grotesque claim for WP Engine&#39;s revenues.<br><br></div><div>It&#39;s even more outrageous that Automattic has chosen trademarks as their method to <a href="https://tech.slashdot.org/story/24/10/04/1925239/matt-mullenweg-wordpressorg-just-belongs-to-me">get their &quot;Al Capone&quot;</a> when up until 2018 they were part owners of WP Engine before selling their stake to Silver Lake!<br><br></div><div>And yet, I can see where this is coming from. <a href="https://rubyonrails.org/">Ruby on Rails</a>, the open-source web framework I created, has been used to create businesses worth hundreds of billions of dollars combined. Some of those businesses express their gratitude and self-interest by supporting the framework with dedicated developers, membership of <a href="https://rubyonrails.org/foundation">The Rails Foundation</a>, or conference sponsorships. But many also do not! And that is absolutely their right, even if it occasionally irks a little.<br><br></div><div>That&#39;s the deal. That&#39;s open source. I give you <a href="https://world.hey.com/dhh/the-open-source-gift-exchange-2171e0f0">a gift of code</a>, you accept the terms of the license. There cannot be a second set of shadow obligations that might suddenly apply, if you strike it rich using the software. Then the license is meaningless, the clarity all muddled, and certainty lost.<br><br></div><div>Look, Automattic can change their license away from the GPL any time they wish. The new license will only apply to new code, though, and WP Engine, or anyone else, are eligible to fork the project. That&#39;s what happened with Redis after Redis Labs dropped their BSD license and went with a commercial source-available alternative. <a href="https://valkey.io/">Valkey</a> was forked from the last free Redis version, and now that&#39;s where anyone interested in an open-source Redis implementation is likely to go.<br><br></div><div>But I suspect Automattic wants to have their cake and eat it too. They want to retain WordPress&#39; shine of open source, but also be able to extract their pound of flesh from any competitor that might appear, whenever they see fit. Screw that.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39923
title: Open source royalty and mad kings
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/open-source-royalty-and-mad-kings-a8f79d16
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I&#39;m solidly in favor of the <a href="https://en.wikipedia.org/wiki/Benevolent_dictator_for_life">Benevolent Dictator For Life (BDFL) model</a> of open source stewardship. This is how projects from Linux to Python, from Laravel to Ruby, and yes, Rails, have kept their cohesion, decisiveness, and forward motion. It&#39;s a model with decades worth of achievements to its name. But it&#39;s not a mandate from heaven. It&#39;s not infallible.</div><div><br>Now I am loathe to even open this discussion. Because I&#39;ve weathered more than <a href="https://world.hey.com/dhh/no-railsconf-faa7935e">my fair share</a> of bad-faith attempts on my own stewardship, and witnessed the show trials of several others. It doesn&#39;t take much for contentious issues within a project, or societal moral panics outside it, to seed dethroning mobs. Which will hijack then eulogize <em>The Will of The Community</em>, as though <em>that</em> somehow deserved the mandate from heaven.</div><div><br>Half the advantage of the BDFL model is exactly in allowing for unpopular decisions to be made without the lethargic mores of committees and bureaucracy! <a href="https://world.hey.com/dhh/open-source-is-neither-a-community-nor-a-democracy-606abdab">Open source is not a democracy</a>, and we all benefit from that fact, whether we accept it or not.</div><div><br>So what follows is not a categorical argument. I believe in the social utility of an open source royalty. One crowned on the virtues of initiative, perseverance, contributions, and technical excellence.<br><br></div><div>Matt Mullenweg has earned his crown in the land of WordPress. He created the system, and for twenty years has been its prime champion and cheerleader. His achievements are obvious. Half the damn internet runs on WordPress! There&#39;s an industry worth billions feeding theme designers, plugin makers, hosting companies, and Matt&#39;s own Automattic enterprise. It&#39;s a first-rate open source success story.</div><div><br>But it&#39;s also one that has taken a dark turn since <a href="https://world.hey.com/dhh/automattic-is-doing-open-source-dirty-b95cf128">Automattic went to war with WP Engine (WPE)</a> over a claim that the latter pay 8% of its revenues as a tithe approximate under the guise of &quot;giving back more&quot;. The leverage of extraction started as a spurious trademark claim, but has since escalated into <a href="https://yro.slashdot.org/story/24/10/03/1354214/wp-engine-sues-wordpress-for-libel-extortion">what WPE has alleged as extortion</a>, and what I see as a seemingly never-ending series of dramatic overreaches and breaches of open source norms. Especially the introduction of <a href="https://wptavern.com/wordpress-org-login-gets-mandatory-affiliation-checkbox-following-wp-engine-dispute">the login loyalty oath</a>, and now with <a href="https://x.com/wp_acf/status/1845169499064107049">the expropriation of WPE&#39;s Advanced Custom Fields (ACF) plugin</a>.</div><div><br>That&#39;s a lot, so let&#39;s start from the end. The most recent escalation, and, in my opinion, the most unhinged, is the expropriation of the ACF plugin. Automattic first answered WPE&#39;s lawsuit by blocking engineers from the latter from accessing the WordPress.org plugin registry, which is used to distribute updates and security patches. It then used the fact that WPE no longer had access to the registry to expropriate the plugin, including reviews and download stats!! <a href="https://wordpress.org/plugins/advanced-custom-fields/">The ACF entry now points to Automattic&#39;s own Secure Custom Fields</a>.</div><div><br>For a dispute that started with a claim of &quot;trademark confusion&quot;, there&#39;s an incredible irony in the fact that Automattic is now hijacking users looking for ACF onto their own plugin. And providing as rational for this unprecedented breach of open source norms that ACF needs maintenance, and since WPE is no longer able to provide that (given that they were blocked!), Automattic has to step in to do so. I mean, what?!</div><div><br>Imagine this happening on npm? Imagine Meta getting into a legal dispute with Microsoft (the owners of GitHub, who in turn own npm), and Microsoft responding by directing GitHub to ban all Meta employees from accessing their repositories. And then Microsoft just takes over the official React repository, pointing it to their own Super React fork. This is the kind of crazy we&#39;re talking about.</div><div><br>Weaponizing open source code registries is something we simply cannot allow to form precedence. They must remain neutral territory. Little Switzerlands in a world of constant commercial skirmishes.</div><div><br>And that&#39;s really the main reason I care to comment on this whole sordid ordeal. If this fight was just one between two billion-dollar companies, as Automattic and WPE both are, I would not have cared to wade in. But the principles at stake extend far beyond the two of them.<br><br></div><div>Using an open source project like WordPress as leverage in this contract dispute, and weaponizing its plugin registry, is an endangerment of an open source peace that has reigned decades, with peace-time dividends for all. Not since <a href="https://en.wikipedia.org/wiki/SCO%E2%80%93Linux_disputes">the SCO-Linux nonsense</a> of the early 2000s have we faced such a potential explosion in fear, doubt, and uncertainty in the open source realm on basic matters everyone thought they could take for granted.<br><br></div><div>So while I always try to keep things from getting personal, I&#39;ll break practice to make this plea: Matt, don&#39;t turn into a mad king. I hold your work on WordPress and beyond in the highest esteem. And I recognize the temptation of gratitude grievances, arising from beneficiaries getting more from our work than they return in contributions. But that must remain a moral critique, not a commercial crusade. You can&#39;t just extract by force that which you believe to be owed beyond the license agreement on a whim.<br><br></div><div>Please don&#39;t make me cheer for a private-equity operator like Silver Lake, Matt. Don&#39;t make me wish for them to file an emergency injunction to stop the expropriation of ACF.<br><br></div><div>It&#39;s not too late. Yes, some bridges have been burned, but look at those as sunk cost. Even in isolation, the additional expense from here on out to continue this conquest is not going to be worth it either. There&#39;s still time to turn around. To strike a modest deal where all parties save some face. I implore you to pursue it.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39934
title: To the crazy ones
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/to-the-crazy-ones-e43822c7
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>In an earlier era, we&#39;d all have been glued to the television to cheer <a href="https://x.com/SpaceX/status/1845442658397049011">SpaceX successfully catching Starship&#39;s returning booster rocket</a> on the first try. I remember my father talking about seeing Apollo 11 make it to the moon. That was a lifelong memory for him. And I remember, as a six-year old boy, watching the fatal Challenger explosion on TV. That&#39;s been a lifelong memory for me. Reaching for space, in triumph or tragedy, ought to be special. <br><br></div><div>But today it&#39;s often just another post that quickly scrolls by on your feed. Maybe you pause for a minute, but the moment easily gets compressed to the same level of gravitas as someone getting punched in the face or an extra cute cat. The spectacle has been completely commoditized. The grand gesture is gone. It now takes effort to actually marvel when something truly spectacular occurs. Like shooting the Starship, 50 feet taller than the Statue of Liberty, towards space, and seeing it stick the landing to perfection.</div><div><br>You should make that effort. Embrace that marvel. Don&#39;t be cynical. Don&#39;t let transient party politics cloud the moment. Musk was once considered to be on the blue team, now he&#39;s on the red team. Little of that will matter in the long term. But propelling progress forward definitely will.</div><div><br>And speaking of Mr Musk, what an insane week for him, and for everyone excited about progress. <a href="https://x.com/Tesla/status/1844583703604772893">Cybertaxis</a>, <a href="https://x.com/Tesla/status/1843922599765590148">robot bartenders</a>, <a href="https://x.com/Tesla/status/1844584591408910512">art-deco people carriers</a>, and now returning starships. This is exactly the kind of willing the future into existence that leaps of progress depend on. Who cares whether all these incredible ambitions arrive right on time or not.</div><div><br>Because ambition this crazy is only likely to emerge from someone equally and sufficiently nuts. And I mean that in the most admirable way possible. Musk is nuts. He&#39;s one of the crazy ones. A true original. Easy to hate, impossible to ignore.</div><div><br>And that&#39;s what gets me. Everyone find it easy to nod in agreement with <a href="https://basicappleguy.com/basicappleblog/heres-to-the-crazy-ones">Jobs&#39; ode to To The Crazy Ones</a>. Everyone wants to believe that they&#39;d support &quot;the misfits, the rebels, the troublemakers&quot;. That they too would cheer for those who are &quot;not fond of rules. And... have no respect for the status quo&quot;.</div><div><br>But they won&#39;t and they don&#39;t. Most people are either <a href="https://paulgraham.com/conformism.html">aggressively or passively conformist</a>. They squirm when The Crazy Ones actually attempt to change the world. They don&#39;t see genius as often as they see transgressors.  A failure to comply and comport. And they don&#39;t like it.<br><br></div><div>I like it. Not crazy for the sake of crazy, but crazy for the sake of progress. Demonstrable, undeniable, awe-inspiring progress. And that&#39;s what Mr Musk has brought us and continues to bring us.<br><br>To infinity and beyond, you crazy spaceman! 🫡</div>
</div>


guid: tag:world.hey.com,2005:World::Post/39962
title: Capture less than you create
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/capture-less-than-you-create-c30e462e
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I beam with pride when I see companies like Shopify, GitHub, Gusto, Zendesk, Instacart, Procore, Doximity, Coinbase, and others claim billion-dollar valuations from work done with Rails. It&#39;s beyond satisfying to see this much value created with a web framework I&#39;ve spent the last two decades evolving and maintaining. A beautiful prize from a life&#39;s work realized.</div><div><br>But it&#39;s also possible to look at this through another lens, and see a huge missed opportunity! If hundreds of billions of dollars in valuations came to be from tools that I originated, why am I not at least a pétit billionaire?! What missteps along the way must I have made to deserve life as merely a rich software entrepreneur, with so few direct, personal receipts from the work on Rails?</div><div><br>This line of thinking is lethal to the open source spirit.<br><br></div><div>The moment you go down the path of gratitude grievances, you&#39;ll see ungrateful ghosts everywhere. People who owe you something, if they succeed. A ratio that&#39;s never quite right between what you&#39;ve helped create and what you&#39;ve managed to capture. If you let it, it&#39;ll haunt you forever.</div><div><br>So don&#39;t! Don&#39;t let the success of others diminish your satisfaction with your own efforts. Unless you&#39;re literally Mark Zuckerberg, Elon Musk, or Jeff Bezos, there&#39;ll always be someone richer than you!<br><br></div><div>The rewards I withdraw from open source flow from all the happy programmers who&#39;ve been able to write Ruby to build these amazingly successful web businesses with Rails. That enjoyment only grows the more successful these business are! The more economic activity stems from Rails, the more programmers will be able to find work where they might write Ruby.<br><br></div><div>Maybe I&#39;d feel different if I was a starving open source artist holed up somewhere begrudging the wheels of capitalism. But fate has been more than kind enough to me in that regard. I want for very little, because I&#39;ve been blessed sufficiently. That&#39;s a special kind of wealth: Enough.<br><br></div><div>And that&#39;s also the open source spirit: To let a billion lemons go unsqueezed. To capture vanishingly less than you create. To marvel at a vast commons of software, offered with no strings attached, to any who might wish to build.<br><br>Thou shall not lust after thy open source&#39;s users and their success.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40106
title: Our cloud-exit savings will now top ten million over five years
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/our-cloud-exit-savings-will-now-top-ten-million-over-five-years-c7d9b5bd
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>We <a href="https://world.hey.com/dhh/we-have-left-the-cloud-251760fb">finished</a> pulling seven cloud apps, including <a href="https://hey.com/">HEY</a>, out of AWS and onto our own hardware last summer. But it took until the end of that year for all the long-term contract commitments to end, so 2024 has been the first clean year of savings, and we&#39;ve been pleasantly surprised that they&#39;ve been even better than originally estimated.<br><br></div><div>For 2024, we&#39;ve brought the cloud bill down from the original $3.2 million/year run rate to $1.3 million. That&#39;s a saving of almost two million dollars per year for our setup! The reason it&#39;s more than <a href="https://world.hey.com/dhh/we-stand-to-save-7m-over-five-years-from-our-cloud-exit-53996caa">our original estimate of $7 million over five years</a> is that we got away with putting all the new hardware into our existing data center racks and power limits.<br><br></div><div>The expenditure on <a href="https://world.hey.com/dhh/the-hardware-we-need-for-our-cloud-exit-has-arrived-99d66966">all that new Dell hardware</a> – about $700,000 in the end – was also entirely recouped during 2023 while the long-term commitments slowly rolled off. Think about that for a second. This is gear we expect to use for the next five, maybe even seven years! All paid off from savings accrued during the second half of 2023. Pretty sweet!<br><br></div><div>But it&#39;s about to get sweeter still. The remaining $1.3 million we still spend on cloud services is all from AWS S3. While all our former cloud compute and managed database/search services were on one-year committed contracts, our file storage has been locked into a four(!!)-year contract since 2021, which doesn&#39;t expire until next summer. So that&#39;s when we plan to be out.</div><div><br>We store almost 10 petabytes of data in S3 now. That includes a lot of super critical customer files, like for Basecamp and HEY, stored in duplicate via separate regions. We use a mixture of storage classes to get an optimized solution that weighs reliability, access, and cost. But it&#39;s still well over a million dollars to keep all this data there (and that&#39;s after the big long-term commitment discounts!).<br><br></div><div>When we move out next summer, we&#39;ll be moving to a dual-DC <a href="https://www.purestorage.com/">Pure Storage</a> setup, with a combined 18 petabytes of capacity. This setup will cost about the same as a year&#39;s worth of AWS S3 for the initial hardware. But thanks to the incredible density and power efficiency of the Pure flash arrays, we can also fit these within our existing data center racks. So ongoing costs are going to be some modest service contracts, and we expect to save another four million dollars over five years.<br><br></div><div>This brings our total projected savings from the combined cloud exit to well over ten million dollars over five years! While getting faster computers and much more storage.<br><br></div><div>Now, as with all things cloud vs on-prem, it&#39;s never fully apples-to-apples. If you&#39;re entirely in the cloud, and have no existing data center racks, you&#39;ll pay to rent those as well (but you&#39;ll probably be shocked at how cheap it is compared to the cloud!). And even for our savings estimates, the target keeps moving as we require more hardware and more storage as Basecamp and HEY continues to grow over the years.</div><div><br>But it&#39;s still remarkable that we&#39;re able to reap savings of this magnitude from leaving the cloud. We&#39;ve been out for just over a year now, and the team managing everything is still the same. There were no hidden dragons of additional workload associated with the exit that required us to balloon the team, as some spectators speculated when we announced it. All the answers in our <a href="https://world.hey.com/dhh/the-big-cloud-exit-faq-20274010">Big Cloud Exit FAQ</a> continue to hold.<br><br></div><div>It&#39;s still work, though! Running apps the size of <a href="https://basecamp.com/">Basecamp</a> and HEY across two data centers (and soon at least one more internationally!) requires a substantial and dedicated crew. There&#39;s always work to be done maintaining all these applications, databases, virtual machines, and yes, occasionally, even requesting a power supply or drive swap on a machine throwing a warming light (but <a href="https://deft.com/">our white gloves at Deft</a> take care of that). But most of that work was something we had to do in the cloud as well!</div><div><br>Since we originally announced <a href="https://world.hey.com/dhh/why-we-re-leaving-the-cloud-654b47e0">our plans to leave the cloud</a>, there&#39;s been a <a href="https://x.com/MichaelDell/status/1780672823167742135">surge of interest</a> in doing the same across the industry. The motto of the 2010s and early 2020s – all-cloud, everything, all the time – seems to finally have peaked. And thank heavens for that!</div><div><br>The cloud can still make a lot of sense, though. Especially in the very early days when you don&#39;t even need a whole computer or are unsure whether you&#39;ll still be in business by the end of the year. Or when you&#39;re dealing with enormous fluctuations in load, like what motivated Amazon to create AWS in the first place.</div><div><br>But as soon as the cloud bills start to become substantial, I think you owe it to yourself, your investors, and common business sense to at least do the math. How much are we spending? What would it cost to buy these computers instead of renting them? Could we try moving some part of the setup onto our own hardware, maybe using <a href="https://kamal-deploy.org/">Kamal</a> or a similar tool? The potential savings from these answers can be shocking.<br><br>At <a href="https://37signals.com/">37signals</a>, we&#39;re looking forward to literally deleting our AWS account come this summer, but remain grateful for the service and the lessons we learned while using the platform. It&#39;s obvious why Amazon continues to lead in cloud. And I&#39;m also grateful that it&#39;s <a href="https://aws.amazon.com/blogs/aws/free-data-transfer-out-to-internet-when-moving-out-of-aws/">now entirely free to move your data out of S3</a>, if you&#39;re leaving the platform for good. Makes the math even better. So long and thanks for all the fish!</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40379
title: What you know that just ain't so
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/what-you-know-that-just-ain-t-so-ab6f4bb1
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>The fun bit about business is in all the answers you don&#39;t have. Should we be priced higher or lower or leave it alone? Should we chase these customers over here or those customers over there? Should we add more features or polish the ones we have? There&#39;s endless variation in every one of those questions, and you can&#39;t reason your way to conclusion. Only testing against reality will really give you an answer. And even then, reality can be &quot;wrong&quot;.<br><br></div><div>Meaning that even valid results of your experiments can steer you astray. Maybe you ran your pricing test too short to know what the second-order effect of losing sign-ups in favor of a higher revenue-per-customer will be, even if it nets out positively for the first year. Maybe presenting your new features came with a new website design, and the latter was what actually moved the needle. It&#39;s very hard to reduce any interesting question in business to a perfect experiment. Best you usually get is more or less confidence.<br><br></div><div>Which is fine! We don&#39;t need to know everything for sure before taking action. In fact, the hallmark of a good business person is their ability to make calculated bets based on half a story and a hunch.</div><div><br>But the key is to remember that what you won was a bet, not a trophy made of truth. And while you can to be grateful for the good outcome, you need to remember that whatever conclusions you draw from it need to remain suspect.</div><div><br>This is just as true when you lose the bet. That&#39;s when you&#39;re liable to believe that &quot;we tried that, didn&#39;t work&quot; represents some universal statement of fact. When in reality, the lesson is more like &quot;we tried SOMETHING and that SOMETHING didn&#39;t work&quot;. In order to remember that &quot;we could try SOMETHING ELSE and THAT might work&quot;.<br><br></div><div>Because if you don&#39;t, you&#39;ll eventually become a prisoner to every bet you&#39;ve made. Convinced that half the opportunities in the world just don&#39;t apply to your situation and the other half is a slam dunk. Nonsense.<br><br></div><div>It&#39;s okay to collect your winnings even if you aren&#39;t exactly sure why you won. It&#39;s okay to take some losses even if you can&#39;t explain exactly where it went wrong. In fact, it&#39;s better than okay to resist coming up with a definitive story either which way. Because as soon as you write that story down, it tends to become rigid rather than open to reinterpretation.<br><br></div><div>An open mind is always willing to let the story twist, willing to revisit the setup, and willing to test everything from timing to premise on another day.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40389
title: The spells are spent
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/the-spells-are-spent-beaa675b
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>They just don&#39;t work any more, those baseless accusations that anyone we disagree with is a racist, misogynist, fascist. After being invoked en masse and in vain for the better part of the past decade, their power to shock and awe is finally gone. All that&#39;s left is a weak whimper. Good fucking riddance.<br><br></div><div>The problem with accusations like that is that they eventually have to be backed by proof or they&#39;ll bounce like a rubber check. And when even the most mundane political or moral positions were able to earn one of those *ist-y labels, the entire enterprise of throwing them around was bound to go bankrupt. And now it has.</div><div><br>Whatever controversy calling <a href="https://world.hey.com/dhh/the-waning-days-of-dei-s-dominance-9a5b656c">the peak of DEI</a> might have garnered two years ago is certainly gone now. Being professionally offended by every little thing, seeing micro-aggressions around every corner, and rendering the entire world through a narrow oppressed/oppressor lens is back to the niche disposition once more.</div><div><br>This particular preference falsification, where people just go along with what&#39;s in vogue to keep their head down, has left the zeitgeist. For a hot minute, it really did seem like <em>everyone</em> was immersed in critical-theory thinking and the rest of the woke orthodoxies. But that was shadows on the wall, distorted to thrice their size from the angle of the light. <br><br></div><div>Now the angle has changed, so the shadows have shrunk. That big scary mob that once was has been reduced to near impotence in most arenas, including the biggest of all, the US presidential election. That&#39;s a win for everyone whether they like Donald Trump or not.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40460
title: Too much therapy at work
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/too-much-therapy-at-work-f79ac95c
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>Many years ago, Jason and I hired a COO at 37signals, but ended up letting them go after just a year (many reasons, another story). This happened not long before one of our company meet-ups, so we thought it fitting to discuss the matter in-person. What a mistake. The session turned into a group therapy session lasting hours, with a free-flowing out-pour of every anxiety under the sun. <br><br></div><div>Some might look at group therapy, with its sharing of emotional stories and vulnerability, as a good thing. And I&#39;m sure it can be, in the right setting. But that setting is not work. Especially not with the entire company present as participants.<br><br></div><div>But that&#39;s where a therapy-infused corporate culture and language often leads. It&#39;s a natural extension of &quot;holding the space&quot;, of too much navel-gazing &quot;mindfulness&quot;, of a posture of nurture and care that borders the patronizing.</div><div><br>It&#39;s okay to be disappointed or frustrated or anxious at work. That&#39;s part of the experience working with and especially for other people! But where things go astray is when there&#39;s an expectation that these emotions always need to be <em>processed</em> during the 9-5 by your manager (rather than after hours with a licensed therapist).</div><div><br>It&#39;s also based on a fundamental misconception that everything can be made better for everyone by talking more about it. For some people, men especially, the better way out of a bad situation is to feel useful. There&#39;s <a href="https://www.buzzfeed.com/daniellaemanuel/men-rather-do-than-therapy">a whole meme</a> dedicated to &quot;men would rather X than go the therapy&quot;, which is posited as a point of derision rather than recognizing taking some/any/all actions as a legitimate coping strategy.<br><br></div><div>See, there&#39;s another one of those therapy words: coping. Belonging to the same lexicon as trauma, rumination, and self-care. I&#39;m sure these are all useful and helpful labels in the right therapeutic context, but again, that just isn&#39;t work. </div><div><br>There&#39;s a reason licensed therapists are bound by a whole host of ethical boundaries when working with clients. They can&#39;t be intertwined with the client&#39;s friends or family or colleagues. They must be competent in the specific areas where they recommend interventions. There are all sorts of healthy constraints on the relationship.</div><div><br>Those constraints can&#39;t apply at work when you&#39;re treating the 1-1 as an hour on the Freudian couch or turn the all-hands into a group therapy session. It&#39;s the same problem with the excessive pathologizing of children that Abigail Shrier covered so well in her book <a href="https://www.amazon.com/gp/product/B0CBYHTV2D/">Bad Therapy</a> (one of my favorite reads from 2024!).<br><br></div><div>It&#39;s easy to read all of the above as cold or dismissive, but please don&#39;t. It&#39;s possible to share the same genuine care for people while disagreeing on the methods and the context that&#39;s due to serve them best. And it&#39;s also possible to look at the increase in therapy thinking, language, and methods in the workplace as an abject failure of modern corporate culture. An increase that&#39;s making people more fragile, <a href="https://world.hey.com/dhh/be-less-precious-b20bf8c3">more precious</a>, more incapable of coping with the most basic expectations of disappointments or adversity on the job.<br><br></div><div>That to me is as sound of a theory for trying something else as you could ever have. What we&#39;ve been doing for the last couple of decades is busted, and it&#39;s time to accept that. Get therapy out of the office and let&#39;s hand it back to the shrinks.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40476
title: House rules in Fortnite
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/house-rules-in-fortnite-16e0e5e8
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>We play a lot of <a href="https://www.fortnite.com/">Fortnite</a> at our house. It&#39;s a great game for teaching kids cooperative discipline, and in a remarkably wholesome setting to boot (no blood, cartoon styling). I&#39;ve had no qualms involving all three of our boys from an early age in the family squad, including our two youngest from around age four.<br><br></div><div>Since we started playing, I&#39;ve just had two primary house rules:<br><br></div><ol><li>Stay together.</li><li>No complaining.</li></ol><div><br>Sounds simple, but it&#39;s ever-so tempting to stray from the squad to chase your own goal of getting better gear, and it comes easy to blame your brother when the other team gets you. Especially when you&#39;re still a preschooler!</div><div><br>But that&#39;s why Fortnite is such an effective tool for teaching discipline. Because if you want to win in a team-based context like that, you have to work together as a team, and you&#39;ll quickly realize that sticking to the rules makes that way more likely.</div><div><br>It&#39;s also teaches you how to lose gracefully. If you get all pissy and blamey when you&#39;re knocked out, the session ends, because nobody wants to listen to that (especially dad!). So if you want to play more, and get better, you better start tempering your frustrations. Wonderful life skill to develop early.</div><div><br>Equally, it&#39;s a delightful game to beat together. Unlike something like Mario Kart or Smash Brothers, which pits the family against itself (also fun, but less learning!), Fortnite puts us all on the same team, striving for the same objective, and in line to celebrate together when we&#39;re successful.</div><div><br>When you add it all up, it&#39;s one of my favorite activities with the kids. It&#39;s highly rewarding to see them internalize both the big life lessons mentioned above, as well as the nitty-gritty tactical insights, like always seeking higher ground, securing cover, and having proper backup before engaging.</div><div><br>All screen time is not created equal.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40490
title: Obsessive problem solving followed by aimless wandering
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/obsessive-problem-solving-followed-by-aimless-wandering-b8e94e0a
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I haven&#39;t felt any urge to tinker with my Linux setup in months. This after spending much of the spring and into summer furiously and obsessively trying every PC out there to find the perfect replacement for the Mac, diving deep with Ubuntu, and codifying my findings in the <a href="https://omakub.org/">Omakub</a> project. But now it&#39;s done, and I&#39;m left enjoying the Apple-free spoils of a new, better place without any recurring work.<br><br></div><div>It was the same experience getting out of the cloud. For months, I spent all my time building <a href="https://kamal-deploy.org/">Kamal</a>, examining server components, and plotting our path. But then <a href="https://world.hey.com/dhh/why-we-re-leaving-the-cloud-654b47e0">we did it</a>, and then <a href="https://world.hey.com/dhh/we-have-left-the-cloud-251760fb">it was done</a>. </div><div><br>Ditto with <a href="https://rubyonrails.org/2024/11/7/rails-8-no-paas-required">Rails 8</a>. Huge push to get the Solid Trifecta to line up with a release that included Propshaft and the authentication generator, and the rest of all the amazing steps forward I covered in <a href="https://www.youtube.com/watch?v=-cEn_83zRFw&amp;list=PLHFP2OPUpCeb182aDN5cKZTuyjn3Tdbqx&amp;index=1">the Rails World keynote</a>. Now that&#39;s done too, and all new Rails apps enjoy the compressed complexity.</div><div><br>At the company level, most of our work is a marathon. That&#39;s how you stay in business for twenty years and beyond. By sticking with it. But at the executive level, almost all big leaps forward are sprints inspired by a hunch. They have to be sprints, because the level of intensity required to get that hunch over the hill is just too high to sustain for long (unless, I guess, you&#39;re Elon!).</div><div><br>That to me is the best argument for making sure my plate isn&#39;t full of half-eaten commitments. That my calendar isn&#39;t clogged with an endless ream of recurring meetings. Such that my mind remains an open, blank slate when one of those obsessive opportunities <a href="https://www.amazon.com/What-Do-You-Chance/dp/1943200734">flutter by</a>.</div><div><br>See, I&#39;ve come to accept that my best work is a series of sprints punctuated by periods of wandering. It was a knee-jerk protest to <a href="https://www.hey.com/apple/">the stultifying and abusive App Store bureaucracy</a> that eventually lead me to Linux. And it was discovering Linux that lead to Omakub, and making the open source operating system <a href="https://world.hey.com/dhh/linux-as-the-new-developer-default-at-37signals-ef0823b7">the default for new technical staff at 37signals</a>. </div><div><br>It was a deep dive into Docker, originally without any clear mission beyond curiosity, that lead to Kamal, and our path out of the cloud. Oh, and getting enamored by the speed of Gen 4 SSDs was what planted the seed for the Solid Trifecta. <br><br></div><div>I couldn&#39;t have planned any of this even if I wanted to. But I also don&#39;t want to. There are few things more satisfying to me than following a hunch and seeing where it leads, without a commitment to a specific, final destination.</div><div><br>It&#39;s a little like writing. Half the joy of composing these paragraphs come from discovering the arguments as the piece develops. Every essay starts with a hunch, but the final shape is rarely clear until the mind has been left to wrestle with the words for a while.</div><div><br>So that&#39;s why my answer to the usual question of &quot;what&#39;s next?&quot;: I don&#39;t know! Because if I did, I&#39;d already be half-way done doing it. And then it wouldn&#39;t really be next, it&#39;d be now.<br><br></div><div>Finding the next now is the art of wandering, and wandering well takes practice and patience. Don&#39;t rush it.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40600
title: Joining the Shopify board of directors
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/joining-the-shopify-board-of-directors-3c351fbb
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I&#39;ve known Tobi for over twenty years now. Right from the earliest days of Ruby on Rails, when he was building Snowdevil, which eventually became <a href="https://shopify.com">Shopify</a>, to sell snowboards online. Here&#39;s <a href="https://github.com/rails/rails/commit/a544d7aa372a080b77940571a3a169496045670e">his first commit to Rails</a> from 2004, which improved the ergonomics of controller testing. Just one out of <a href="https://contributors.rubyonrails.org/contributors/tobias-lutke/commits">the 131 commits he made to the framework from 2004-2010</a> -- a record still good enough to be in <a href="https://contributors.rubyonrails.org/">the top 100 all-time contributors to Rails</a>!<br><br></div><div>But Tobi&#39;s contributions to Ruby on Rails extend far beyond his individual commits to the framework, creating <a href="https://activemerchant.org/">Active Merchant</a> and the Liquid templating system, or <a href="https://rubyonrails.org/community#alumni">serving on the Rails Core Team</a> back in the early days. With Shopify, Tobi more or less single-handedly <a href="https://x.com/tobi/status/1728524453854756883">killed the zombie argument that Rails couldn&#39;t scale</a> by building the world&#39;s most popular hosted e-commerce platform and routing a sizable portion of all online sales through it.<br><br></div><div>In the process, Tobi built an incredible technical organization to support this effort. Shopify employs a third of the Rails Core Team, developed the YJIT compiler for Ruby, and contributed in a billion other ways. They are without a doubt the most generous benefactor in the Ruby on Rails world.</div><div><br>So when Tobi asked me whether I&#39;d be interested in joining Shopify&#39;s board, I needed no pause to consider the invitation. <a href="https://www.shopify.com/news/david-heinemeier-hansson-board">OF COURSE I WOULD!</a></div><div><br>But to be honest, it wasn&#39;t just a reflexive answer to service the gratitude I&#39;ve felt toward Shopify for many years. It was also to satisfy a selfish curiosity to wrestle with problems at a scale that none of my own work has ever touched. <br><br></div><div>Both in terms of the frontier programming problems inherent in dealing with a <a href="https://signalvnoise.com/svn3/the-majestic-monolith/">majestic monolith</a> clocking in at five million lines of code, and the challenge of guiding thousands of programmers to productively extend it, Shopify deals with a scale several orders of magnitude beyond what I do day-to-day at 37signals. That&#39;s interesting!<br><br></div><div>So too is the sheer magnitude of the impact Shopify is having on the world of commerce. While much of the web is decaying to <a href="https://en.wikipedia.org/wiki/Enshittification">enshitification</a> and entropy, Shopify stores stand out by being faster to browse, quicker to checkout, and easier to trust. That&#39;s enabling a vast array of individual entrepreneurs and businesses to have a competitive shopping experience against the likes of Amazon, without needing huge teams to do it.</div><div><br>It&#39;s always a delight when I <a href="https://akkogear.eu/">find</a> <a href="https://www.lofree.co/">a</a> <a href="https://www.aviatornation.com/">cool</a> <a href="https://us.store.bambulab.com/">store</a>, and I learn that it&#39;s running on Shopify. As I spoke with Tobi about on <a href="https://www.youtube.com/watch?v=uAgHlSLxcTU&amp;t=617s">the announcement show</a>, this was really hammered home after I got into mechanical keyboards. Seemingly every single vendor of thocky and clicky keyboards use Shopify! And when I see that, not only am I sure that buying won&#39;t be a hassle, but I also know I&#39;m not going to get scammed. That&#39;s the Shopify magic: Leveling the commercial playing field between some obscure keyboard maker and the consolidated titans of e-commerce.<br><br></div><div>And now I get to help further that mission from the inside! What a treat. Thanks Tobi!</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40623
title: Cold reading an ADHD affliction
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/cold-reading-an-adhd-affliction-44163793
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>I&#39;m sure there are truly pathological cases of ADHD out there, and maybe taking amphetamines really is a magic pill for some folks. But there clearly is also an entire cottage industry cropping up around convincing perfectly normal people that they suffer from ADHD, and that this explains many unwanted aspects of the human condition.<br><br></div><div>Take this thread I stumbled across on X today by an &quot;ADHD coach&quot;: <a href="https://x.com/dustychipura/status/1858933299227299867">The ADHD Basics</a>. It lists five primary symptoms:<br><br></div><ul><li>Forgetfulness.</li><li>High standards / perfectionism.</li><li>Attraction to novelty.</li><li>Lack of consistency.</li><li>Difficulty establishing/breaking habits.</li></ul><div><br>No wonder we&#39;ve seen an explosion of ADHD diagnosis. This list applies to most humans at least part of the time! I would even say that all five applies to me much of the time. So does this mean I suffer from ADHD and should start taking Adderall? Come on.</div><div><br>This is usually when the hand waving starts: &quot;Sure, you may recognize all those symptoms, but for <em>true</em> ADHD sufferers, they&#39;re just, like, worse!&quot;. Okay, but what kind of diagnostic standard is that?!</div><div><br>The <a href="https://en.wikipedia.org/wiki/Attention_deficit_hyperactivity_disorder">official presentation of ADHD symptoms</a> as listed on Wikipedia isn&#39;t much better than what the five from the ADHD coach either.  It includes markers such as:<br><br></div><ul><li>&quot;Frequently overlooks details or makes careless mistakes&quot;</li><li>&quot;Often cannot quietly engage in leisure activities or play&quot;</li><li>&quot;Often talks excessively&quot;</li><li>&quot;Often has difficulty maintaining focus on one task or play activity&quot;</li><li>&quot;Is frequently easily distracted by extraneous stimuli&quot;</li></ul><div><br>Again, I can recognize myself in several of those from time to time. And if you include the entire list of markers from the DSM-5, I&#39;m sure I can rack up the five+ necessary to earn an official designation of ADHD. That&#39;s just ridiculous.</div><div><br>It&#39;s even worse when it comes to kids, but Abigail Shrier already covered that topic expertly in <a href="https://www.amazon.com/Bad-Therapy-Kids-Arent-Growing/dp/0593542924/">Bad Therapy</a>, so I won&#39;t repeat that here. If only to marvel at the collective insanity where being loud or animated during play is a pathological marker for children! Now that&#39;s crazy. </div><div><br>But I know this is a touchy subject for plenty of parents of kids who struggle in ways that might fall under some of these rubrics. So let&#39;s leave the kids out of this for a minute and focus on the adults instead.<br><br></div><div>A total of 45 million Adderall prescriptions were written in the US in 2023. That&#39;s up from 35 million in 2019. A great many of these were surely made to people who got convinced that being &quot;forgetful&quot; or &quot;attracted to novelty&quot; isn&#39;t just part of being human, but an affliction requiring amphetamines to mitigate.</div><div><br>What this reminds me of is the concept of <a href="https://en.wikipedia.org/wiki/Cold_reading">cold readings</a>. Where a psychic slyly prods for revealing details from their subject while vaguely throwing out potential hooks left, right, and center. The subject is induced to ignore the vagueness that doesn&#39;t apply to their situation, but focus on the inevitable hits that convince someone that what they desperately want to hear is true.<br><br></div><div>I think a lot of people desperately want to hear that there&#39;s a medical reason for why they sometimes can&#39;t focus, don&#39;t feel motivated, forget things, or find breaking bad habits hard (and not something as boring as you need better sleep, regular exercise, and an improved diet). So when ADHD coaches show up to make them feel better with a medical label, it&#39;s compelling to partake in the cold reading, and get the answer you were hoping for.</div><div><br>But that&#39;s nonsense. You don&#39;t need a diagnosis to be a flawed human. It goes for all of us. So if you want to supercharge your morning&#39;s productivity routine by popping a pill or two of amphetamines, own it! Don&#39;t hide behind some label (or think you&#39;re immune to the long-term effects of taking speed either).</div>
</div>


guid: tag:world.hey.com,2005:World::Post/40652
title: Jaguar is lost but Volvo knows the way
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/jaguar-is-lost-but-volvo-knows-the-way-9601033c
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div><a href="https://www.youtube.com/watch?v=rLtFIrqhfng">Jaguar&#39;s new rebrand</a> is getting murdered online, and for good reason. The clichés are as thick as the diversity pandering is dated. CREATE EXUBERANT. LIVE VIVID. DELETE ORDINARY. You&#39;d think these were slogans from a Will Ferrel bit about insufferable marketing trons, but nope, that&#39;s the 2024 campaign for a car maker that won&#39;t be selling any cars until 2026. Utterly tone-deaf, out of tune with the vibe shift, and quite likely the final gasp of a storied but dying British brand. SAD!<br><br></div><div>Contrast this with <a href="https://www.youtube.com/watch?v=cQX-QXxwGvA">the advertisement for Volvo&#39;s latest EX90</a>. It&#39;s a 3:45-minute emotional cinematic ride that illustrates to perfect what it means to have a strong brand. To stand for something, and actually mean it. <br><br></div><div>It&#39;s not even that original! They did <a href="https://www.youtube.com/watch?v=AM-2HlgPftE">a variation of the same theme</a> six years ago for the same car, but that detracts nothing from its brilliance. In fact, the opposite. Brand is like culture: It&#39;s all about repetition and authenticity. Being who you say you are, over and over.<br><br></div><div>Volvo is safety, safety is paramount to parents, so Volvo is for parents. It&#39;s that simple, and it&#39;s that powerful. But only because it&#39;s actually true! You couldn&#39;t run this branding campaign for, say, Toyota, and see the same success. Toyota has their roots in reliability. That&#39;s their story.</div><div><br>But Volvo literally does care. Their history includes <a href="https://www.volvogroup.com/en/about-us/heritage/three-point-safety-belt.html">giving away the patent to the seatbelt</a>. In Sweden, they have a <a href="https://www.youtube.com/watch?v=pi5VytbzvEg">crash response team</a> that goes to the scene of accidents involving Volvo cars to learn how they can become safer (and they&#39;ve been doing this since the 70s!!). And in the UK, the XC90 had no official deaths recorded since the car was introduced in 2004 (<a href="https://autoexpress.co.uk/volvo/xc90/103233/no-fatalities-ever-recorded-in-a-volvo-xc90-in-the-uk">at least per 2018</a>).<br><br></div><div>Volvo also does safety quite differently than most auto makers. They&#39;re not just studying and optimizing for the crash-ratings tests, which is what it seems drive most other manufacturers. Their cars do very well when the test expands to include new scenarios because it&#39;s <a href="https://danluu.com/car-safety/">designed to be best-in-reality</a> not just best-in-test.</div><div><br>All that is to say that the branding strength of Volvo rests on congruence, consistency, and commitment to doing the same thing, a little better every year, for basically an eternity. It&#39;s incredibly inspiring.<br><br></div><div>Frankly, it makes me want to buy a Volvo! Even though by all sorts of natural inclinations (speed/design/heritage), I should be interested in a new Jaguar. But I wouldn&#39;t be caught dead in a Jaguar now. That&#39;s the power of advertisement: To lift and to diminish.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41067
title: The premise trap
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/the-premise-trap-924b8cd9
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>The hardest part for me about collaborating with junior programmers, whether it&#39;s in open source or at work, is avoiding the premise trap. That&#39;s where the fundamental assumptions baked into the first draft of the code aren&#39;t questioned until you&#39;ve already spent far too long improving the implementation. It&#39;s the same with AI.<br><br></div><div>Because AI at the moment is like a superb junior programmer. One with an encyclopedic knowledge about syntax and APIs, but also one saddled with the same propensities to produce overly-complicated, subtly-defective solutions.<br><br></div><div>You could read this as a bullish signal for the future of AI programming. That the current trajectory is tracking with the human programmer&#39;s progression tree, and that eventually, like the best juniors, it&#39;ll graduate to senior levels of competence in the fine details of code aesthetics, novel problem reasoning, and architectural coherence. I hope that&#39;s the case.<br><br></div><div>But that doesn&#39;t change the fact that, as of right now, I&#39;ve yet to see any of the AI models I&#39;ve been using for the past year produce great code within domains that I&#39;m very familiar with. Occasionally there&#39;ll be a glimmer, just like with promising junior programmers, but taken as a whole, the solutions almost always need material amounts of rework.<br><br></div><div>Which is when that premise trap claps!<br><br></div><div>I&#39;ve seen this repeatedly with both the Ruby and JavaScript code that comes out of the AI, so I doubt it&#39;s that particular to one language over another. But the propensity to pull in needless dependencies, the overly-verbose presentation, and the architectural dead ends are there all the time.<br><br>This is what I hear from people who are trying to use AI to write entire systems for them without actually being capable programmers themselves. That it&#39;s an incredible rush to see a prototype come to life in mere minutes, but that actually moving this forward to something that works reliably often turns into a one-step-forwards-two-steps-backwards dance. (Not unlike the many stories someone might have getting catfished by a barely qualified junior programmer on Upwork!).</div><div><br>While that&#39;s frustrating, it makes perfect sense when you consider the training data that has been teaching these models. The endless stream of basic online tutorials, Stack Overflow simplified answers, and the unfortunate reality that a fair chunk of internet programming content is made by the blind leading the blind.</div><div><br>Senior human programmers all got started on the same information diet, but eventually graduated to higher levels of understanding and mastery by working on proprietary code bases. Where all the trade-offs that are absent in tutorial-style code reveal themselves and demand to be weighed with finesse.</div><div><br>I think the next big leap for these models under the current paradigm probably isn&#39;t likely to happen until they&#39;re exposed to a vast corpus on proprietary, corporate code. And how that&#39;s going to happen isn&#39;t entirely clear at the moment.</div><div><br>So in the mean time, as a senior programmer, you&#39;d do well to treat AI as you would a junior programmer. It&#39;s rarely going to save you time asking it to produce an entire system, or even subsystem, if you care about the final quality of the architecture or implementation. Because to verify the assumptions that have been baked into its path will require spending as much time to understand the choices as it would doing the work yourself.<br><br></div><div>I remain bullish on AI writing code for us all, but also remain realistic about its current abilities. As well as alert to the danger of luring more senior programmers, including myself, into signing off on slop, while it saps our stamina for continued learning, as we lean too much on AI writing for us rather than teaching how.<br><br>May this piece age badly within a few short years!</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41358
title: Delusional dreams of excess freedom
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/delusional-dreams-of-excess-freedom-e7507662
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>Jim Carrey <a href="https://www.goodreads.com/quotes/1151805-i-think-everybody-should-get-rich-and-famous-and-do">once said</a> that he hoped everyone could &quot;...get rich and famous and do everything they dreamed of so they can see that it is not the answer&quot;. And while I sorta agree, I think the opposite position also has its appeal: That believing in a material fix to the problem of existence dangles a carrot of hope that&#39;s depressing to go without.</div><div><br>What made me think of Carrey&#39;s quote was <a href="https://vinay.sh/i-am-rich-and-have-no-idea-what-to-do-with-my-life/">this tale of the startup founder behind Loom</a>, who made out with a $60m windfall when his business was sold, and is still working his way through the existential crisis that created. It&#39;s harder than you think to suddenly have all the freedom you ever desired land in your lap. You may just realize that you don&#39;t actually know what to do with it all!</div><div><br>And this predicament isn&#39;t reserved for successful entrepreneurs either. You see miniature revelations of this in many stories of retirement. Workers who after a long life toiling away suddenly arrive at the promised land of unlimited time, the basics taken care of, and full freedom from all responsibilities and obligations. Some literally wither away from all that excess freedom.</div><div><br>One of the Danish newspapers I read recently <a href="https://politiken.dk/debat/art10182189/%C2%BBJeg-tror-der-er-rigtig-mange-pensionister-der-n%C3%A6rmest-g%C3%A5r-i-hundene%C2%AB">published</a> a series on exactly this phenomenon. Pensioners who realize that life without work can be a surprisingly difficult place to find meaning in. That being needed, being useful is far more attractive than leaning back in leisure. And, as a result, more and more senior Danes are returning to the workforce, at least part time, to reclaim some of that meaning.<br><br></div><div>I think you can even draw a connection to the stereotype of rich kids who grow up never being asked to do contribute anything, busy bossing the help around, and as a result end up floundering in a vapid realm of materialism. Condemned rather than blessed.<br><br></div><div>Yes, this all rhymes a bit with <a href="https://www.youtube.com/watch?v=_Wgn0KlSHl4">that iconic scene from The Matrix</a> where Cypher is negotiating a return to blissful ignorance with Agent Smith: I don&#39;t want to remember nothing! Because once you know that the material carrot is just like <a href="https://www.youtube.com/watch?v=uAXtO5dMqEI">the spoon that bends because it doesn&#39;t actually exist</a>, you&#39;re condemned to a life of knowing that what you imagine as nirvana probably isn&#39;t.<br><br></div><div>What beautiful irony: That the prize for catching the carrot is the realization that chasing it was more fun.<br><br></div>
</div>


guid: tag:world.hey.com,2005:World::Post/41367
title: The social media censorship era is over (for now)
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/the-social-media-censorship-era-is-over-for-now-c28c82f2
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>Mark Zuckerberg just announced <a href="https://x.com/tobi/status/1876613776981778556">a stunning pivot</a> for Meta&#39;s approach to social media censorship. Here&#39;s what he&#39;s going to do:<br><br></div><ol><li>Replace third-party fact checkers with community notes ala X.</li><li>Allow free discussion on immigration, gender, and other topics that were heavily censored in the past, as well as let these discussions freely propagate (and go viral).</li><li>Focus moderation on illegal activities, like child exploitation, frauds, and scams, instead of political transgressions.</li><li>Relocate the moderation team from California to Texas to address political bias from within the team.</li></ol><div><br>This new approach is going to govern all the Meta realms, from Facebook to Threads to Instagram. Meaning it&#39;ll affect the interactions of some three billion people around the globe. In other words, this is huge.</div><div><br>As to be expected, many are highly skeptical of Zuckerberg&#39;s motives. And for good reason. Despite making <a href="https://about.fb.com/news/2019/10/mark-zuckerberg-stands-for-voice-and-free-expression/">a soaring speech</a> to the values of free speech back in 2019, Meta, together with Twitter, became one of the primary weapons for a political censorship regime that went into overdrive during the pandemic.<br><br></div><div>Both Meta and Twitter received <a href="https://x.com/mtaibbi/status/1598822959866683394">direct instructions</a> from the US government, among other institutions, on what was to be considered allowable speech and what was to be banned. The specifics shifted over those awful years, but everything from questioning the origins of the Covid virus to disputing vaccine efficacy to objections on mass migration to the Hunter Biden laptop leak all qualified for heavy-handed intervention.<br><br></div><div>The primary rhetorical fig leaves for this censorship regime was &quot;hate speech&quot; and &quot;misinformation&quot;. Terms that almost immediately lost all objective content, and turned into mere descriptors of &quot;speech we don&#39;t like&quot;. Either because it was politically inconvenient or because it offended certain holy tenants of the <a href="https://www.amazon.com/Woke-Racism-Religion-Betrayed-America/dp/0593423062/">woke religion</a> that reigned at the time.<br><br></div><div>But that era is now over. Between Meta and X, the gravity of the global discourse has swung dramatically in favor of free expression. I suspect that YouTube and Reddit will eventually follow suit as well. But even if they don&#39;t, it won&#39;t really matter. The forbidden opinions and inconvenient information will still be able to reach a wide audience.<br><br></div><div>That&#39;s a momentous and positive moment for the world. And it&#39;s a particularly proud moment for America, since this is all downstream from the country&#39;s first amendment protection of free speech.<br><br></div><div>But it&#39;s also adding to the growing chasm between America and Europe. And the United Kingdom in particular. While America is recovering from the authoritarian grip on free speech in terms of both social media policies and broader social consequences (remember cancel culture?), the Brits are <a href="https://www.bbc.com/news/articles/cr548zdmz3jo">doubling down</a>.<br><br></div><div>Any post on social media made in Britain is liable to have those cute little bobbies show up at your door with a not-so-cute warrant for your arrest. The delusional UK police commissioner is even <a href="https://x.com/politvidchannel/status/1874889002073182329">threatening to &quot;come after&quot; people</a> from around the world, if they write bad tweets.<br><br></div><div>And Europe isn&#39;t far behind. Thierry Breton, the former European Commissioner, spent much of last year threatening American tech companies, and <a href="https://www.politico.eu/article/eu-elon-musk-donald-trump-interview-thierry-breton-letter-social-media/">Elon Musk in particular</a>, with draconian sanctions, if they failed to censor on the EU&#39;s behest. He has thankfully since been dismissed, but the sentiment of censorship is alive and well in the EU.<br><br></div><div>This is why the world needs America. From the UK to the EU to Brazil, China, Russia, and Iran, political censorship is very popular. And for a couple of dark years in the US, it looked like the whole world was about to be united in an authoritarian crackdown on speech of all sorts.<br><br></div><div>But Elon countered the spell. His acquisition of Twitter and its transformation into X was <em>the</em> pivotal moment for both American and global free speech. And if you allow yourself to zoom out from the day-to-day antics of the meme lord at large, you should be able to see clearly how the timeline split.</div><div><br>I know that&#39;s hard to do for a lot of people who&#39;ve traded in their Trump Derangement Syndrome diagnosis for a Musk Derangement Syndrome variety (or simply added it to their inventory of mental challenges). And I get it. It&#39;s hard to divorce principles from people! We&#39;re all liable to mix and confuse the two.</div><div><br>And speaking of Trump, which, to be honest, I try not to do too often, because I know how triggering he is,  credit is still due. There&#39;s no way this incredible vibe shift would have happened as quickly or as forcefully without his comeback win.</div><div><br>Now I doubt that any of his political opponents are going to give him any credit for this, even if they do perhaps quietly celebrate the pivot on free speech. And that&#39;s OK. I don&#39;t expect miracles, and we don&#39;t need them either. You don&#39;t need to love every champion of your principles to quietly appreciate their contributions.<br><br></div><div>Which very much reminds me of the historic lawsuit that the Jewish lawyers at the <a href="https://mjhnyc.org/events/when-nazis-came-to-illinois-the-history-of-the-skokie-case/">ACLU (in its former glory) fought to allow literal nazis to match</a> in the streets of Skokie, Illinois. That case goes to the crux of free speech. That in order for you to voice your dissent on Trump or Musk or whatever, you need the protection of the first amendment to cover those who want to dissent in the opposite direction too.</div><div><br>That&#39;s a principle that&#39;s above the shifting winds and vibes of whoever is in power. It&#39;s entire purpose is to protect speech that&#39;s unpopular with the rulers of the moment. And as we&#39;ve seen, electoral fortunes can change! It&#39;s in your own self interest to affirm a set of rules for participation in the political debate that live beyond the what&#39;s expedient for partisan success in the short term.</div><div><br>I for one am stoked about Meta&#39;s pivot on censorship. I&#39;ve historically not exactly been Mark Zuckerberg&#39;s biggest fan, and I do think it&#39;s fair to question the authenticity of him and this move, but I&#39;m not going to let any of that get in the way of applauding this monumental decision. The world needs America and its exceptional principles more than ever. I will cheer for Zuckerberg without reservation when he works in their service.</div><div><br>Now how do we get the UK and the EU to pivot as well?</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41531
title: Failed integration and the fall of multiculturalism
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/failed-integration-and-the-fall-of-multiculturalism-77296314
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>For decades, the debate in Denmark around  problems with mass immigration was stuck in a self-loathing blame game of &quot;failed integration&quot;. That somehow, if the Danes had just tried harder, been less prejudice, offered more opportunities, the many foreigners with radically different cultures would have been able to integrate successfully. If not in the first generation, then the second. For much of this time, I thought that was a reasonable thesis. But reality has proved it wrong.<br><br>If literally every country in Europe has struggled in the same ways, and for decades on end, to produce the fabled &quot;successful integration&quot;, it&#39;s not a compelling explanation that it&#39;s just because the Danes, Swedes, Norweigans, Germans, French, Brits, or Belgians just didn&#39;t try hard enough. It&#39;s that the mission, on the grand and statistical scale, was impossible in many cases.<br><br>As Thomas Sowell tells us, this is because there are no solutions to intractable, hard problems like cultural integration between wildly different ways of living. Only trade offs. Many of which are unfavorable to all parties.<br><br>But by the same token, just because the overall project of integrating many of the most divergent cultures from mass immigrations has failed, there are many individual cases of great success. Much of the Danish press, for example, has for years propped up the hope of broad integration success by sharing hopeful, heartwarming stories of highly successful integration. And you love to see it.<br><br>Heartwarming anecdotes don&#39;t settle trade offs, though. They don&#39;t prove a solution or offer a conclusion either.<br><br>I think the conclusion at this point is clear. First, cultural integration, let alone assimilation, is incredibly difficult. The more divergent the cultures, the more difficult the integration. And for some combinations, it&#39;s outright impossible.<br><br>Second, the compromise of multiculturalism has been an abject failure in Europe. Allowing parallel cultures to underpin parallel societies is poison for the national unity and trust.<br><br>Which brings us to another bad social thesis from the last thirty-some years: That national unity, character, and belonging not only isn&#39;t important, but actively harmful. That national pride in history, traditions, and culture is primarily an engine of bigotry.<br><br>What a tragic thesis with catastrophic consequences.<br><br>But at this point, there&#39;s a lot of political capital invested into all these bad ideas. In sticking with the tired blame game. Thinking that what hasn&#39;t worked for fifty years will surely start working if we give it five more. <br><br>Now, I actually have a nostalgic appreciation for the beautiful ideals behind such hope for humanity, but I also think that at this point it is as delusional as it is dangerous.<br><br>And I think it&#39;s directly responsible for the rise of so-called populist movements all over Europe. They&#39;re directly downstream from the original theses of success in cultural integration going through just-try-harder efforts as well as the multicultural compromise. A pair of ideas that had buy-in across much of the European board until reality simply became too intolerable for too many who had to live with the consequences.<br><br>Such widespread realization doesn&#39;t automatically correct the course of a societal ship that&#39;s been sailing in the wrong direction for decades, of course. The playbook that took DEI and wokeness to blitzkrieg success in the States, by labeling any dissent to those ideologies racist or bigoted, have also worked to hold the line on the question of mass immigration in Europe until very recently. <br><br>But I think the line is breaking in Europe, just as it recently did in America. The old accusations have finally lost their power from years of excessive use, and suppressing the reality that many people can see with their own eyes is getting harder.<br><br>I completely understand why that makes people anxious, though. History is full of examples of combative nationalism leading us to dark edges. And, especially in Germany, I can understand the historical hesitation when there&#39;s even a hint of something that sounds like what they heard in the 30s.<br><br>But you can hold both considerations in your head at the same time without losing your wits. Mass immigration to Europe has been a failure, and the old thesis of naive hope has to get replaced by a new strategy that deals with reality. AND that not all proposed fixes by those who diagnosed the situation early are either sound or palatable.<br><br>World history is full of people who&#39;ve had the correct diagnosis but a terrible prescription. And I think it&#39;s fair to say that it&#39;s not even obvious what the right prescription is at this point!<br><br>Vibrant, strong societies surely benefit from some degree of immigration. Especially from culturally-compatible regions based on national and economic benefit. But whatever the specific trade-offs taken from here, it seems clear that for much of Europe, they&#39;re going to look radically different than they&#39;ve done in the past three decades or so.<br><br>Best get started then.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41543
title: MEGA
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/mega-a0f62cd4
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>Trump is back at the helm of the United States, and the majority of Americans are optimistic about the prospect. Especially the young. In a poll by CBS News, it&#39;s the 18-29 demographic that&#39;s most excited, with a whopping two-thirds answering in the affirmative to being optimistic about the next four years under Trump. And I&#39;m right there with them. The current American optimism is infectious!<br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--png">
      <a download="signal-2025-01-19-19-30-15-791.png" title="Download signal-2025-01-19-19-30-15-791.png" data-click-proxy-target="lightbox_link_blob_1975974927" href="https://world.hey.com/dhh/a0f62cd4/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2NQL01aMSIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--90b6759cb5e8939d64eb40d38e35acc42f4d295f/signal-2025-01-19-19-30-15-791.png?disposition=attachment">
</a>
  </figure><br><br>While Trump has undoubtedly been the catalyst, this is a bigger shift than any one person. After spending so long lost in the wilderness of excessive self-criticism and self-loathing, there&#39;s finally a broad coalition of the willing working to get the mojo back.<br><br>This is what&#39;s so exhilarating about America. The big, dramatic swings. The high stakes. The long shots. And I like this country much better when it&#39;s confident in that inherent national character.<br><br>Of course all this is political. And of course Trump is triggering for many. Just like his opponent would have been if she had won. But this moment is not just political, it&#39;s beyond that. It&#39;s economic, it&#39;s entrepreneurial, it&#39;s technological. Optimism is infectious.<br><br>As someone with a foot on both the American and European continent, I can&#39;t help being jealous with my euro leg. Europe is stuck with monumental levels of pessimism at the moment, and it&#39;s really sad to see.<br><br>But my hope is that Europe, like usual, is merely a few years behind the American revival in optimism. That it&#39;s coming to the old world eventually.<br><br>This is far more an article of faith than of analysis, mind you. I can also well imagine Europe sticking with Eurocrat thinking, spinning its wheels with grand but empty proclamations, issuing scorning but impotent admonishments of America, and doubling down on the regulatory black hole.<br><br>Neither path is given. Europe was competitive with America on many economic terms as recently as 15 years ago. But Europe also lacks the ability to change course quite like the Americans. So the crystal ball is blurry.<br><br>Personally, I choose faith. Optimism must win. Pessimism is literally for losers.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41573
title: Waiting on red
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/waiting-on-red-6894032f
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>Americans often laugh when they see how often Danes will patiently, obediently wait on the little red man to turn green before crossing an empty intersection, in the rain, even at night. Nobody is coming! Why don&#39;t you just cross?! It seems silly, but the underlying philosophy is anything but. It&#39;s load bearing for a civil society like Denmark.<br><br>Because doing the right thing every time can be put on autopilot, and when most people follow even the basic norms consistently, the second-order effects are profound. Like the fact that <a href="https://cities-today.com/copenhagen-named-as-worlds-safest-city/">Copenhagen is one of the absolute safest major cities</a> in the world.<br><br>But the Danes also know that norms fray if they&#39;re not enforced, so they vigorously pursue even small infractions. The Danish police regularly <a href="https://x.com/KobenhavnPoliti/status/1881696508996882687">celebrating ticketing bicyclists</a> making even minor mistakes (like driving instead of dragging their bike on the sidewalk). And the metro is constantly being patrolled for fare evaders and antisocial behavior.<br><br>It&#39;s broken windows theory on steroids. And it works.<br><br>When we were living in the city for three years following the pandemic, the most startling difference to major US cities was the prevalence of unattended children everywhere, at all hours. Our oldest was just nine years-old when he started taking the metro alone, even at night.<br><br>How many American parents would feel comfortable letting their nine-year old take the L in Chicago or the subway in Manhattan? I don&#39;t know any. And as a result, you just don&#39;t see any unattended children do this. But in Copenhagen it&#39;s completely common place.<br><br>This is the prize of having little tolerance for antisocial behavior in the public space. When you take away the freedom from crackheads and bums to smoke up on the train or sleep in the park, you grant the freedom to nine-year olds to roam the city and for families to enjoy the park at dusk.<br><br>This is the fundamental error of suicidal empathy. That tolerance of the deranged and dangerous few can be kept a separate discussion from the freedom and safety of the many. These are oppositional forces. The more antisocial behavior you excuse, the further families will retract into their protective shell. And suddenly there are no longer children around in the public city space or any appetite for public transit.<br><br>Maybe you have to become a parent to really understand this. I admit that I didn&#39;t give this nearly the same attention before coming a father of three. But the benefit isn&#39;t exclusively about the freedom and safety enjoyed by your own family, it&#39;s also about the ambient atmosphere of living in a city where children are everywhere. It&#39;s a special form of life-affirming luxury, and it&#39;s probably the thing I&#39;ve missed most about Copenhagen since we went back to the US.<br><br>What&#39;s interesting is how much active effort it takes to maintain this state of affairs. The veneer of civil society is surprisingly thin. Norms fray quickly if left unguarded. And it&#39;s much harder to reestablish their purchase on society than to protect them from disappearing in the first place.<br><br>But I also get that it&#39;s hard to connect the dots from afar, though. Many liberals in America keep Denmark as some mythical place where all their policy dreams have come true, without ever wrestling much with what it takes to maintain the social trust that allows those policies to enjoy public support.<br><br>The progressive Nirvana of Denmark is built on a highly conservative set of norms and traditions. It&#39;s yin and yang. So if you&#39;re committed to those progressive outcomes in America, whether it&#39;s the paternity leave, the independent children, or the amazing public transit system, you ought to consider what conservative values it makes sense to accept as enablers rather than obstacles.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41711
title: It burns
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/it-burns-9576a115
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>The first time we had to evacuate Malibu this season was during the Franklin fire in early December. We went to bed with our bags packed, thinking they&#39;d probably get it under control. But by 2am, the roaring blades of fire choppers shaking the house got us up. As we sped down the canyon towards Pacific Coast Highway (PCH), the fire had reached the ridge across from ours, and flames were blazing large out the car windows. It felt like we had left the evacuation a little too late, but they eventually did get Franklin under control before it reached us.<br><br></div><div>Humans have a strange relationship with risk and disasters. We&#39;re so prone to wishful thinking and bad pattern matching. I remember people being shocked when the flames jumped the PCH during the Woolsey fire in 2017. IT HAD NEVER DONE THAT! So several friends of ours had to suddenly escape a nightmare scenario, driving through burning streets, in heavy smoke, with literally their lives on the line. Because the past had failed to predict the future.</div><div><br>I fell into that same trap for a moment with the dramatic proclamations of wind and fire weather in the days leading up to January 7. Warning after warning of &quot;extremely dangerous, life-threatening wind&quot; coming from the City of Malibu, and that overly-bureaucratic-but-still-ominous &quot;Particularly Dangerous Situation&quot; designation. Because, really, how much worse could it be? Turns out, a lot.<br><br></div><div>It was a little before noon on the 7th when we first saw the big plumes of smoke rise from the Palisades fire. And immediately the pattern matching ran astray. Oh, it&#39;s probably just like Franklin. It&#39;s not big yet, they&#39;ll get it out. They usually do. Well, they didn&#39;t.</div><div><br>By the late afternoon, we had once more packed our bags, and by then it was also clear that things actually were different this time. Different worse. Different enough that even Santa Monica didn&#39;t feel like it was assured to be safe. So we headed far North, to be sure that we wouldn&#39;t have to evacuate again. Turned out to be a good move.</div><div><br>Because by now, into the evening, few people in the connected world hadn&#39;t started to see the catastrophic images emerging from the Palisades and Eaton fires. Well over 10,000 houses would ultimately burn. Entire neighborhoods leveled. Pictures that could be mistaken for World War II. Utter and complete destruction.<br><br></div><div>By the night of the 7th, the fire reached our canyon, and it tore through the chaparral and brush that&#39;d been building since the last big fire that area saw in 1993. Out of some 150 houses in our immediate vicinity, nearly a hundred burned to the ground. Including the first house we moved to in Malibu back in 2009. But thankfully not ours.</div><div><br>That&#39;s of course a huge relief. This was and is our Malibu Dream House. The site of that gorgeous home office I&#39;m so fond to share views from. Our home.</div><div><br>But a house left standing in a disaster zone is still a disaster. The flames reached all the way up to the base of our construction, incinerated much of our landscaping, and devoured the power poles around it to dysfunction.</div><div><br>We have burnt-out buildings every which way the eye looks. The national guard is still stationed at road blocks on the access roads. Utility workers are tearing down the entire power grid to rebuild it from scratch. It&#39;s going to be a long time before this is comfortably habitable again.<br><br></div><div>So we left.<br><br></div><div>That in itself feels like defeat. There&#39;s an urge to stay put, and to help, in whatever helpless ways you can. But with three school-age children who&#39;ve already missed over a months worth of learning from power outages, fire threats, actual fires, and now mudslide dangers, it was time to go.</div><div><br>None of this came as a surprise, mind you. After Woolsey in 2017, Malibu life always felt like living on borrowed time to us. We knew it, even accepted it. Beautiful enough to be worth the risk, we said. <br><br></div><div>But even if it wasn&#39;t a surprise, it&#39;s still a shock. The sheer devastation, especially in the Palisades, went far beyond our normal range of comprehension. Bounded, as it always is, by past experiences.<br><br></div><div>Thus, we find ourselves back in Copenhagen. A safe haven for calamities of all sorts. We lived here for three years during the pandemic, so it just made sense to use it for refuge once more. The kids&#39; old international school accepted them right back in, and past friendships were quickly rebooted.</div><div><br>I don&#39;t know how long it&#39;s going to be this time. And that&#39;s an odd feeling to have, just as America has been turning a corner, and just as the optimism is back in so many areas. Of the twenty years I&#39;ve spent in America, this feels like the most exciting time to be part of the exceptionalism that the US of A offers.<br><br>And of course we still are. I&#39;ll still be in the US all the time on both business, racing, and family trips. But it won&#39;t be exclusively so for a while, and it won&#39;t be from our Malibu Dream House. And that burns.<br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="palisades-plumes.jpg" title="Download palisades-plumes.jpg" data-click-proxy-target="lightbox_link_blob_1990451052" href="https://world.hey.com/dhh/9576a115/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RzMzZOMiIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--8aee607f23f14e231969ad51d33aecff2040674c/palisades-plumes.jpg?disposition=attachment">
</a>
  </figure></div>
</div>


guid: tag:world.hey.com,2005:World::Post/41866
title: Servers can last a long time
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/servers-can-last-a-long-time-165c955c
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>We bought sixty-one servers for <a href="https://signalvnoise.com/posts/3968-launch-basecamp-3">the launch of Basecamp 3</a> back in 2015. Dell R430s and R630s, packing thousands of cores and terabytes of RAM. Enough to fill all the app, job, cache, and database duties we needed. The entire outlay for this fleet was about half a million dollars, and it&#39;s only now, almost a decade later, that we&#39;re finally retiring the bulk of them for a full hardware refresh. What a bargain!<br><br></div><div>That&#39;s over 3,500 days of service from this fleet, at a fully amortized cost of just $142/day. For everything needed to run Basecamp. A software service that has grossed hundreds of millions of dollars in that decade.<br><br></div><div>We&#39;ve of course had other expenses beyond hardware from operating Basecamp over the past decade. The ops team, the bandwidth, the power, and the cabinet rental across both our data centers. But none the less, owning our own iron has been a fantastically profitable proposition. Millions of dollars saved over renting in the cloud.</div><div><br>And we aren&#39;t even done deriving value from this venerable fleet! The database servers, Dell R630s w/ Xeon E5-2699 CPUs and 768G of RAM, are getting handed down to some of <a href="https://37signals.com/policies/until-the-end-of-the-internet/">our heritage apps</a>. They will keep on trucking until they give up the ghost.</div><div><br>When we did <a href="https://world.hey.com/dhh/our-cloud-exit-savings-will-now-top-ten-million-over-five-years-c7d9b5bd">the public accounting for our cloud exit</a>, it was based on five years of useful life from the hardware. But as this example shows, that&#39;s pretty conservative. Most servers can easily power your applications much longer than that.<br><br></div><div>Owning your own servers has easily been one of our most effective cost advantages. Together with <a href="https://world.hey.com/dhh/we-once-more-have-no-full-time-managers-at-37signals-f8611085">running a lean team</a>. And managing our costs remains key to <a href="https://37signals.com/04">reaping the profitable fruit</a> from the business. The dollar you keep at the end of the year is just as real whether you earn it or save it.</div><div><br>So you just might want to run those cloud-exit numbers once more with a longer server lifetime value. It might just tip the equation, and motivate you to become a server owner rather than a renter.</div>
</div>


guid: tag:world.hey.com,2005:World::Post/41903
title: Serving the country
author: David Heinemeier Hansson
url: https://world.hey.com/dhh/serving-the-country-9faa5ef3
feedurl: https://world.hey.com/dhh/feed.atom
content_mime_type: text/html
content:
<div class="trix-content">
  <div>In 1940, President Roosevelt tapped <a href="https://en.wikipedia.org/wiki/William_S._Knudsen">William S. Knudsen</a> to run the government&#39;s production of military equipment. Knudsen had spent a pivotal decade at Ford during the mass-production revolution, and was president of General Motors, when he was drafted as a civilian into service as a three-star general. Not bad for a Dane, born just ten minutes on bike from where I&#39;m writing this in Copenhagen!</div><div><br>Knudsen&#39;s leadership raised the productive capacity of the US war machine by a 100x in areas like plane production, where it went from producing 3,000 planes in 1939 to over 300,000 by 1945. He was quoted on his achievement: &quot;We won because we smothered the enemy in an avalanche of production, the like of which he had never seen, nor dreamed possible&quot;.<br><br></div><div>Knudsen wasn&#39;t an elected politician. He wasn&#39;t even a military man. But Roosevelt saw that this remarkable Dane had the skills needed to reform a puny war effort into one capable of winning the Second World War.<br><br></div><div>Do you see where I&#39;m going with this? Elon Musk is a modern day William S. Knudsen. Only even more accomplished in efficiency management, factory optimization, and first-order systems thinking.</div><div><br>No, America isn&#39;t in a hot war with the Axis powers, but for the sake of the West, it damn well better be prepared for one in the future. Or better still, be so formidable that no other country or alliance would even think to start one. And this requires a strong, confident, and sound state with its affairs in order.<br><br></div><div>If you look at the government budget alone, this is direly not so. The US was knocking on a two-trillion-dollar budget deficit in 2024! Adding to a towering debt that&#39;s now north of 36 trillion. A burden that&#39;s already consuming $881 billion in yearly interest payments. More than what&#39;s spent on the military or Medicare. Second to only Social Security on the list of line items.</div><div><br>Clearly, this is not sustainable.<br><br></div><div>This is the context of <a href="https://x.com/DOGE">DOGE</a>. The program, lead by Musk, that&#39;s been deputized by Trump to turn the ship around. History doesn&#39;t repeat, but it rhymes, and Musk is dropping beats that Knudsen would have surely been tapping his foot to. And just like Knudsen in his time, it&#39;s hard to think of any other American entrepreneur more qualified to tackle exactly this two-trillion dollar problem. <br><br></div><div>It is through <a href="https://world.hey.com/dhh/the-musk-algorithm-977bf312">The Musk Algorithm</a> that SpaceX lowered the cost of sending a kilo of goods into lower orbit from the US by well over a magnitude. And now America&#39;s share of worldwide space transit has risen from less than 30% in 2010 to about 85%. Thanks to reusable rockets and <a href="https://www.youtube.com/watch?v=hI9HQfCAw64&amp;t=134s">chopstick-catching landing towers</a>. Thanks to Musk.<br><br></div><div>Or to take a more earthly example with Twitter. Before Musk took over, Twitter had revenues of $5 billion and earned $682 million. After the take over, <a href="https://www.wsj.com/finance/banks-sell-5-5-billion-of-x-loans-after-investor-interest-surges-4b84f89c?st=RLZrtU&amp;reflink=desktopwebshare_permalink">X has managed to earn $1.25 billion on $2.7 billion in revenue</a>. Mostly thank to the fact that <a href="https://world.hey.com/dhh/need-it-take-7-500-people-to-run-twitter-a8cb36a6">Musk cut 80% of the staff</a> out of the operation, and savaged the cloud costs of running the service.</div><div><br>This is not what people expected at the time of the take over! Not only did many commentators believe that Twitter was going to collapse from the drastic costs in staff, they also thought that the financing for the deal would implode. Chiefly as a result of advertisers withdrawing from the platform under intense media pressure. But that just didn&#39;t happen.<br><br></div><div>Today, the debt used to take over Twitter and turn it into X is <a href="https://www.wsj.com/finance/banks-sell-5-5-billion-of-x-loans-after-investor-interest-surges-4b84f89c?st=RLZrtU&amp;reflink=desktopwebshare_permalink">trading at 97 cents on the dollar</a>. The business is twice as profitable as it was before, and arguably as influential as ever. All with just a fifth of the staff required to run it. Whatever you think of Musk and his personal tweets, it&#39;s impossible to deny what an insane achievement of efficiency this has been!</div><div><br>These are just two examples of Musk&#39;s incredible ability to defy the odds and deliver the most unbelievable efficiency gains known to modern business records. And we haven&#39;t even talked about taking Tesla from producing 35,000 cars in 2014 to making 1.7 million in 2024. Or turning xAI into a major force in AI by assembling a 100,000 H100 cluster at <a href="https://www.entrepreneur.com/business-news/nvidia-ceo-jensen-huang-praises-elon-musk-xai-superhuman/481325">&quot;superhuman&quot;</a> pace. <br><br></div><div>Who wouldn&#39;t want such a capacity involved in finding the waste, sloth, and squander in the US budget? Well, his political enemies, of course!</div><div><br>And I get it. Musk&#39;s magic is balanced with mania and even a dash of madness. This is usually the case with truly extraordinary humans. The taller they stand, the longer <a href="https://www.youtube.com/watch?v=OhzBo0dZNpY">the shadow</a>. Expecting Musk to do what he does and then also be a &quot;normal, chill dude&quot; is delusional.<br><br></div><div>But even so, I think it&#39;s completely fair to be put off by his tendency to fire tweets from the hip, opine on world affairs during all hours of the day, and offer his support to fringe characters in politics, business, and technology. I&#39;d be surprised if even the most ardent Musk super fans don&#39;t wince a little every now and then at some of the antics.<br><br></div><div>And yet, I don&#39;t have any trouble weighing those antics against the contributions he&#39;s made to mankind, and finding an easy and overwhelming balance in favor of his positive achievements.<br><br></div><div>Musk is exactly the kind of formidable player you want on your team when you&#39;re down two trillion to nothing, needing a Hail Mary pass for the destiny of America, and eager to see the West win the future.<br><br></div><div>He&#39;s a modern-day Knudsen on steroids (or Ketamine?). Let him cook.<br><br>  <figure class="attachment attachment--preview attachment--lightboxable attachment--jpg">
      <a download="time-knudsen.jpg" title="Download time-knudsen.jpg" data-click-proxy-target="lightbox_link_blob_2000075626" href="https://world.hey.com/dhh/9faa5ef3/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHNLd2RxdXpaMyIsImV4cCI6bnVsbCwicHVyIjoiYmxvYl9pZCJ9fQ==--d3552ae7dc2c6519e047f5e04816a3a3d5d34ed1/time-knudsen.jpg?disposition=attachment">
</a>
  </figure></div>
</div>


guid: https://decuser.github.io/lisp/2023/07/24/lisp-1.5
title: LISP 1.5 running on an emulated IBM 7094
author: decuser
url: https://decuser.github.io/lisp/2023/07/24/lisp-1.5.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/lisp/2023/07/24/lisp-1.5.html
content_mime_type: text/html
content:
<p>This note describes how to set up and run the oldest available ancestor of all extant LISPS and Schemes.</p>

<p>LISP 1.5 was the first LISP that was made generally available. It is available to run on the OpenSIMH IBM 7094 emulator.</p>

<p><img src="/assets/img/lisp/Terminal_001.png" alt="one" /></p>

<!--more-->

<h2 id="resources">Resources</h2>

<ul>
  <li>
    <p><strong>LISP 1.5 Programmer’s Manual</strong> <a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf</a> or grab a <a href="/assets/files/lisp/LISP%201.5%20Programmers%20Manual.pdf">local copy</a></p>
  </li>
  <li>
    <p><strong>LISP 1.5 Primer</strong> <a href="https://www.softwarepreservation.org/projects/LISP/book/Weismann_LISP1.5_Primer_1967.pdf">https://www.softwarepreservation.org/projects/LISP/book/Weismann_LISP1.5_Primer_1967.pdf</a> or grab a <a href="/assets/files/lisp/Weismann_LISP1.5_Primer_1967.pdf">local copy</a></p>
  </li>
  <li>
    <p><strong>OpenSIMH</strong> <a href="https://opensimh.org/">https://opensimh.org/</a></p>
  </li>
  <li>
    <p><strong>LISP 1.5 2023 tarball</strong> <a href="/assets/files/lisp/lisp15.2023.tar.gz">lisp15.2023.tar.gz</a> - note, this is a slightly modified version of Andre Luvisi’s tarball.</p>
  </li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Linux - I’m running Debian 12 (bookworm)</li>
  <li>A build environement (make, cc, and ld) - build-essential package on debian systems</li>
  <li>OpenSIMH - any reasonably recent version should work</li>
</ul>

<h2 id="getting-started">Getting Started</h2>

<ul>
  <li>Create a workarea</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/workarea/retro/lisp-1.5/{dist,work}
cd ~/workarea/retro/lisp-1.5/dist
</code></pre></div></div>

<ul>
  <li>Download the tarball</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://decuser.github.io/assets/files/lisp/lisp15.2023.tar.gz
</code></pre></div></div>

<h2 id="build-the-system">Build the System</h2>

<ul>
  <li>Unpack the tarball and the utils tarball inside it</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ../work
tar xvzf ../dist/lisp15.2023.tar.gz
cd lisp15
tar xvf utils-1.1.8.tar.gz
</code></pre></div></div>

<ul>
  <li>Build the utils and copy txt2bcd to a directory on the path (critically important)</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd utils
make
cp ./txt2bcd ~/bin
</code></pre></div></div>

<ul>
  <li>Test txt2bcd</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>txt2bcd
Usage: txt2bcd infile [outfile] [reclen, default 80 [blklen, default 84]]
</code></pre></div></div>

<ul>
  <li>Clean up from utilts build</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ..
rm -fr utils
</code></pre></div></div>

<ul>
  <li>Actually build the system</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>make realclean; make
</code></pre></div></div>

<p>A successful build will result in a sysboot.tp in the current directory and a transcript similar to this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm -f sys.log scratch/*
(cd build; make clean)
make[1]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
(cd boottape; make clean)
make[2]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
rm -f syscore.tp sys.log scratch/*
make[2]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
make[1]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
rm -f sysboot.tp
(cd build; make realclean)
make[1]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
(cd boottape; make clean)
make[2]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
rm -f syscore.tp sys.log scratch/*
make[2]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
rm -f sysboot.tp boottape/lisp.obj
make[1]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
(cd build; make sysboot.tp)
make[1]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
asm7090/asm7090 -o boottape/lisp.obj chist/lisp.job
(cd boottape; make)
make[2]: Entering directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
i7094 lispimg.ini library.txt

IBM 7094 simulator Open SIMH V4.1-0 Current        simh git commit id: cf47a20f
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-13&gt; at mta1 -r scratch/lisp.job.mt
%SIM-INFO: MTA1: unit is read only
%SIM-INFO: MTA1: Tape Image 'scratch/lisp.job.mt' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-14&gt; at mta2 scratch/systap.tp
%SIM-INFO: MTA2: creating new file
%SIM-INFO: MTA2: Tape Image 'scratch/systap.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-15&gt; at mta3 syscore.tp
%SIM-INFO: MTA3: creating new file
%SIM-INFO: MTA3: Tape Image 'syscore.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-16&gt; at mta4 scratch/syspot.tp
%SIM-INFO: MTA4: creating new file
%SIM-INFO: MTA4: Tape Image 'scratch/syspot.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-17&gt; at mta5 scratch/sysppt.tp
%SIM-INFO: MTA5: creating new file
%SIM-INFO: MTA5: Tape Image 'scratch/sysppt.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-19&gt; at cdr scratch/corrcards
%SIM-INFO: CDR: creating new file
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-20&gt; at cdp scratch/lispout.whatever
%SIM-INFO: CDP: creating new file
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape/lispimg.ini-21&gt; at lpt sys.log
%SIM-INFO: LPT: creating new file

HALT instruction, PC: 10524 (TRA 10523)
Goodbye
make[2]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build/boottape'
cp boottape/syscore.tp sysboot.tp
make[1]: Leaving directory '/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/build'
cp build/sysboot.tp sysboot.tp
</code></pre></div></div>

<h2 id="run-the-system">Run the system</h2>

<p>If you successfully built the system, you should be ready to run LISP 1.5. A few words are in order… Running LISP 1.5, so far as I can tell, consists of running the simulator against a tape image of a lisp source file. So, you type LISP 1.5 compatible code into a file and then invoke the emulator against that file. It processes your source and outputs the result.</p>

<p>The tarball includes three source files that are in the correct format to be run in LISP 1.5:</p>

<ul>
  <li>
    <p>factorial.txt - test code that will calculate the factorial of a number, in this case 10, which should result in 3,628,800.</p>
  </li>
  <li>
    <p>funarg.txt - a function argument test</p>
  </li>
  <li>
    <p>propcal.txt - test the Wang algorithm for propositional calculus</p>
  </li>
</ul>

<p>To run them, invoke the emulator and provide the ini file to initialize the emulator and the text file with the source, for example, to run the factorial program type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>i7094 lisptape.ini factorial.txt
</code></pre></div></div>

<p>A successful run will generate a sys.log file and the output will resemble:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>IBM 7094 simulator Open SIMH V4.1-0 Current        simh git commit id: cf47a20f
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-12&gt; at mta1 -r scratch/lisp.job.mt
%SIM-INFO: MTA1: unit is read only
%SIM-INFO: MTA1: Tape Image 'scratch/lisp.job.mt' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-13&gt; at mta2 -r sysboot.tp
%SIM-INFO: MTA2: unit is read only
%SIM-INFO: MTA2: Tape Image 'sysboot.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-14&gt; at mta3 scratch/syscore.tp
%SIM-INFO: MTA3: Tape Image 'scratch/syscore.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-15&gt; at mta4 scratch/syspot.tp
%SIM-INFO: MTA4: Tape Image 'scratch/syspot.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-16&gt; at mta5 scratch/sysppt.tp
%SIM-INFO: MTA5: Tape Image 'scratch/sysppt.tp' scanned as SIMH format
/home/wsenn/workarea/retro/lisp-1.5/work/lisp15/lisptape.ini-20&gt; at lpt sys.log
%SIM-INFO: LPT: creating new file

HALT instruction, PC: 10524 (TRA 10523)
Goodbye
</code></pre></div></div>

<p>The results will be in the file sys.log:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat sys.log
             TEST  FACTORIAL



  THE TIME ( 0/ 0  000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS .....   -LEWIS CARROLL-
 EVALQUOTE OPERATOR AS OF 1 MARCH 1961.    INPUT LISTS NOW BEING READ.


  THE TIME ( 0/ 0  000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS .....   -LEWIS CARROLL-
  FUNCTION   EVALQUOTE   HAS BEEN ENTERED, ARGUMENTS..
 DEFINE

 (((FACTORIAL (LAMBDA (X) (COND ((EQUAL X 0) 1) (T (TIMES X (FACTORIAL (
SUB1 X)))))))))

 END OF EVALQUOTE, VALUE IS ..
 *TRUE*

  FUNCTION   EVALQUOTE   HAS BEEN ENTERED, ARGUMENTS..
 FACTORIAL

 (10)


 END OF EVALQUOTE, VALUE IS ..
 3628800



  THE TIME ( 0/ 0  000.0) HAS COME, THE WALRUS SAID, TO TALK OF MANY THI
NGS .....   -LEWIS CARROLL-
 END OF EVALQUOTE OPERATOR
             FIN      END OF LISP RUN
</code></pre></div></div>

<h2 id="conclusions">Conclusions</h2>

<p>This was an interesting exploration. I enjoyed getting it up and running with a minimum of fuss. I didn’t appreciate the fact that it was effectively a job submission environment and not an interactive system.</p>

<p>Something to note is the use of evaluquote as the top-level, not eval…</p>

<p>In the next exploration, I will investigate a system that is much more modern, yet directly descended from LISP 1.5. Rob Pike’s LISP 1.5 interpreter in Go. A minimal implementation of 1.5’s evalquote from pg. 13 of the Programming LISP 1.5 text.</p>

<h3 id="afterthoughts">Afterthoughts</h3>

<p>Andre Luvisi’s original work exists (for now) in Archive.org’s repository of crawled pages:</p>

<ul>
  <li><strong>Luvisi’s LISP 1.5 tarball</strong> <a href="https://web.archive.org/web/20211202101850/http://web.sonoma.edu/users/l/luvisi/lisp/lisp15.tar.gz">https://web.archive.org/web/20211202101850/http://web.sonoma.edu/users/l/luvisi/lisp/lisp15.tar.gz</a></li>
</ul>

<p>It won’t build because of duplicate names (fin and fon are defined in multiple files), but the fix is easy, just change line 19 of prsf2.c to read:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>static char fin[300], fon[300];
</code></pre></div></div>

<p>and it should work the same way as described above.</p>

<p>Later - Will</p>

<p><em>post added 2023-07-24 19:28:00 -0600</em></p>


guid: https://decuser.github.io/lisp/2023/07/24/pike-lisp-1.5-in-go
title: Rob Pike’s LISP 1.5 in Go running on Debian 12
author: decuser
url: https://decuser.github.io/lisp/2023/07/24/pike-lisp-1.5-in-go.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/lisp/2023/07/24/pike-lisp-1.5-in-go.html
content_mime_type: text/html
content:
<p>This note describes how to set up and run Rob Pike’s LISP 1.5 in Go.</p>

<p>LISP 1.5 was the first LISP that was made generally available. Rob Pike implemented a minimalist version of the EVALQUOTE function described on page 13 of the LISP 1.5 Programmer’s Manual <a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf</a> or grab a <a href="/assets/files/lisp/LISP%201.5%20Programmers%20Manual.pdf">local copy</a></p>

<p><img src="/assets/img/lisp/Terminal_002.png" alt="one" /></p>

<!--more-->

<h2 id="resources">Resources</h2>

<ul>
  <li>
    <p><strong>LISP 1.5 Programmer’s Manual</strong> <a href="https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf">https://www.softwarepreservation.org/projects/LISP/book/LISP%201.5%20Programmers%20Manual.pdf</a> or grab a <a href="/assets/files/lisp/LISP%201.5%20Programmers%20Manual.pdf">local copy</a></p>
  </li>
  <li>
    <p><strong>LISP 1.5 Primer</strong> <a href="https://www.softwarepreservation.org/projects/LISP/book/Weismann_LISP1.5_Primer_1967.pdf">https://www.softwarepreservation.org/projects/LISP/book/Weismann_LISP1.5_Primer_1967.pdf</a> or grab a <a href="/assets/files/lisp/Weismann_LISP1.5_Primer_1967.pdf">local copy</a></p>
  </li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Linux - I’m running Debian 12 (bookworm)</li>
</ul>

<h2 id="getting-started">Getting Started</h2>

<ul>
  <li>Get Go</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ~/Downloads
wget https://go.dev/dl/go1.20.6.linux-amd64.tar.gz
</code></pre></div></div>

<ul>
  <li>Install Go</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo rm -rf /usr/local/go &amp;&amp; sudo tar -C /usr/local -xzf go1.20.6.linux-amd64.tar.gz
</code></pre></div></div>

<ul>
  <li>Add it to the path (logout and back in after making change)</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vi ~/.bashrc
export PATH=$PATH:/usr/local/go/bin
</code></pre></div></div>

<ul>
  <li>Create a work area</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/workarea/go/pike
cd ~/workarea/go/pike
</code></pre></div></div>

<ul>
  <li>Clone Rob Pike’s repo</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/robpike/lisp.git
</code></pre></div></div>

<ul>
  <li>Initialize the module</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd lisp/
go mod init
</code></pre></div></div>

<p>Should result in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go: creating new go.mod: module robpike.io/lisp
go: to add module requirements and sums:
	go mod tidy
</code></pre></div></div>

<ul>
  <li>Tidy the module</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go mod tidy
</code></pre></div></div>

<p>Good news is no news.</p>

<ul>
  <li>Build the module</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>go build
</code></pre></div></div>

<p>Again, good news is no news.</p>

<ul>
  <li>Run the lisp</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./lisp lib.lisp
(fac gcd ack equal not negate mapcar length opN member union intersection)
&gt; (add 1 3)
4
&gt;
^D
</code></pre></div></div>

<p>Tool around and try things out. Pretty amazing work.</p>

<p>Later - Will</p>

<p><em>post added 2023-07-24 19:28:00 -0600</em></p>


guid: https://decuser.github.io/lisp/2023/07/30/pdp-1-lisp
title: pdp1-lisp running on an emulated PDP-1
author: decuser
url: https://decuser.github.io/lisp/2023/07/30/pdp-1-lisp.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/lisp/2023/07/30/pdp-1-lisp.html
content_mime_type: text/html
content:
<p>This note describes how to set up and run PDP-1 lisp. It’s a pretty brief walkthrough. If you run into any issues, let me know.</p>

<p><img src="/assets/img/lisp/Terminal_003.png" alt="one" /></p>

<!--more-->
<p>PDP-1 LISP is a LISP 1.5 dialect created at BBN by L. Peter Deutsch. It was released as a DECUS tape in 1964, it currently runs on the Open SimH PDP-1 emulator.</p>

<h2 id="resources">Resources</h2>
<ul>
  <li>
    <p><strong>The LISP Implementation for the PDP-1 Computer</strong>
<a href="https://www.computerhistory.org/pdp-1/_media/pdf/DEC.pdp_1.1964.102650371.pdf">https://www.computerhistory.org/pdp-1/_media/pdf/DEC.pdp_1.1964.102650371.pdf</a></p>
  </li>
  <li>
    <p><strong>OpenSIMH</strong> <a href="https://opensimh.org/">https://opensimh.org/</a></p>
  </li>
  <li>
    <p><strong>Trailing-edge Software Kits</strong> <a href="http://simh.trailing-edge.com/software.html">http://simh.trailing-edge.com/software.html</a></p>
  </li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Linux - I’m running Debian 12 (bookworm)</li>
  <li>A build environement (make, cc, and ld) - build-essential package on debian systems</li>
  <li>OpenSIMH - any reasonably recent version should work</li>
</ul>

<h2 id="getting-started">Getting Started</h2>

<ul>
  <li>Create a workarea</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/workarea/retro/pdp-1-lisp
cd ~/workarea/retro/pdp-1-lisp
</code></pre></div></div>

<ul>
  <li>Download the pdp-1 lisp software kit and upack it</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget http://simh.trailing-edge.com/kits/lispswre.zip
unzip lispswre.zip
</code></pre></div></div>

<h2 id="compile-the-macro-assembler">Compile the macro assembler</h2>

<p><code class="language-plaintext highlighter-rouge">cc macro1.c -o macro1</code></p>

<h2 id="assemble-the-lisp-interpreter">Assemble the lisp interpreter</h2>

<p><code class="language-plaintext highlighter-rouge">./macro lisp.mac</code></p>

<h2 id="create-an-ini-file-for-the-pdp-1-emulator">Create an ini file for the PDP-1 emulator</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &lt;&lt;EOF &gt;run.ini
set cpu mdv
load lisp.rim
d extm_init 1
run

d tw 7777
c

d tw 400
c

d ss 2
save lisp.sav

echo READY
c
EOF
</code></pre></div></div>

<h2 id="run-the-emulator-and-load-the-lisp-binary">Run the emulator and load the lisp binary</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pdp1 run.ini

PDP-1 simulator Open SIMH V4.1-0 Current        simh git commit id: cf47a20f

HALT instruction, PC: 002353 (CLA LAT CLI)

HALT instruction, PC: 002357 (CLA LAT)

HALT instruction, PC: 000005 (STF6)
READY
</code></pre></div></div>

<p>The system is ready to act as a repl, but it’s funny, you have to end a lisp form with a space in order for the interpreter to process it! So, if you want to add two numbers, you would use
(plus 2 2) , with a trailing space - as in, (plus 2 2)<SPACE>, replacing <SPACE> with the actual space character ' '.</SPACE></SPACE></p>

<p>The system will reply with the evaluation:</p>

<p>a</p>

<p>To end the simulation, type CTL-e, then at the sim&gt; prompt type q to exit.</p>

<p>A full session would look like this:</p>

<p><img src="/assets/img/lisp/Terminal_003.png" alt="one" /></p>

<p>If you encounter an interpreter error, during your session, the system will halt after displaying the error message, but can often be continued, by typing <code class="language-plaintext highlighter-rouge">c</code> at the sim&gt; prompt.</p>

<p>This is similar to modern lisps that dump you into a debugger where you can look around and then restart the interpreter, only the debugger, in this case, is simh.</p>

<p>Later - Will</p>

<p><em>post added 2023-07-30 20:02:00 -0600</em></p>


guid: https://decuser.github.io/lisp/2023/07/31/franz-lisp
title: Franz LISP Opus 32 in 3BSD running on an emulated VAX 780
author: decuser
url: https://decuser.github.io/lisp/2023/07/31/franz-lisp.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/lisp/2023/07/31/franz-lisp.html
content_mime_type: text/html
content:
<p>This note describes how to set up and run Franz LISP Opus 32 running on 3BSD running on an emulated VAX 780. This version of Franz LISP is Opus 32 and it is a LISP 1.5 derived LISP from 1979.</p>

<p><img src="/assets/img/lisp/Terminal_004.png" alt="one" /></p>

<!--more-->
<p>Wikipedia notes:</p>

<blockquote>
  <p>In computer programming, Franz Lisp is a discontinued Lisp programming language system written at the University of California, Berkeley (UC Berkeley, UCB) by Professor Richard Fateman and several students, based largely on Maclisp and distributed with the Berkeley Software Distribution (BSD) for the Digital Equipment Corporation (DEC) VAX minicomputer. Piggybacking on the popularity of the BSD package, Franz Lisp was probably the most widely distributed and used Lisp system of the 1970s and 1980s.</p>
</blockquote>

<blockquote>
  <p>The name is a pun on the composer and pianist Franz Liszt.</p>
</blockquote>

<h2 id="resources">Resources</h2>

<ul>
  <li>
    <p><strong>3BSD Tape File</strong> <a href="https://sourceforge.net/projects/bsd42/files/Install%20tapes/3%20BSD/">https://sourceforge.net/projects/bsd42/files/Install%20tapes/3%20BSD/</a></p>
  </li>
  <li>
    <p><strong>Franz Lisp Manual - Opus 38.69 from 1982</strong> <a href="https://www.softwarepreservation.org/projects/LISP/franz/Franz_Lisp_July_1983.pdf">https://www.softwarepreservation.org/projects/LISP/franz/Franz_Lisp_July_1983.pdf</a></p>
  </li>
</ul>

<p>This is the earliest manual I could find. When you’re online in 3BSD, there is documentation for the Franz LISP Opus 32, in <code class="language-plaintext highlighter-rouge">/usr/doc/lisp</code>.</p>

<ul>
  <li><strong>Gunkies 3BSD Page</strong> <a href="https://gunkies.org/wiki/3BSD">https://gunkies.org/wiki/3BSD</a></li>
</ul>

<p>An invaluable resource for getting things up an running with a minimum of fuss.</p>

<ul>
  <li><strong>OpenSIMH</strong> <a href="https://opensimh.org/">https://opensimh.org/</a></li>
</ul>

<p>The simulator I’m using.</p>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Linux - I’m running Debian 12 (bookworm)</li>
  <li>A build environement (make, cc, and ld) - build-essential package on debian systems</li>
  <li>OpenSIMH - any reasonably recent version should work</li>
</ul>

<h2 id="overview">Overview</h2>

<p>Much of this note is based on the Gunkies 3BSD page. Specifically, tboot.ini, dboot.ini, uudecode, and the 3BSD boot block are from that page <a href="https://gunkies.org/wiki/3BSD">https://gunkies.org/wiki/3BSD</a>. This note is just organized differently and getting 3BSD running here, is specifically for running Franz LISP.</p>

<h2 id="getting-started">Getting Started</h2>

<ul>
  <li>Create a workarea</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/workarea/retro/franz/{dist,work}
cd ~/workarea/retro/franz/dist
</code></pre></div></div>

<ul>
  <li>Download 3BSD and a bootblock</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://decuser.github.io/assets/files/lisp/3bsd.tap.bz2
wget https://decuser.github.io/assets/files/lisp/boot3bsd
</code></pre></div></div>

<ul>
  <li>Verify you have the right files</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>shasum *
f8b59d933896678f04e9a0b0284466563d650c24  3bsd.tap.bz2
482464bbd3ceb8ec9f02036ad06dbe5a181572e2  boot3bsd
</code></pre></div></div>

<ul>
  <li>Unpack the tape file and copy the bootblock into work</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ../work
bzcat ../dist/3bsd.tap.bz2 &gt; 3bsd.tap
cp ../dist/boot3bsd .
</code></pre></div></div>

<ul>
  <li>Create an ini file for booting from tape</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &lt;&lt;EOF &gt;tboot.ini
set tto 7b
set rq dis
set lpt dis
set rl dis
set hk dis
set rq dis
set rqb dis
set rqc dis
set rqd dis
set ry dis
set ts dis
set tq dis
set dz lines=8
set rp0 rp06
at rp0 rp06.disk
set tu0 te16
at tu0 3bsd.tap
D 50000 20009FDE
D 50004 D0512001
D 50008 3204A101
D 5000C C113C08F
D 50010 A1D40424
D 50014 008FD00C
D 50018 C1800000
D 5001C 8F320800
D 50020 10A1FE00
D 50024 00C139D0
D 50028 04c1d004
D 5002C 07e15004
D 50030 0000f750
go 50000
go 0
EOF
</code></pre></div></div>

<h2 id="build-the-system">Build the system</h2>

<ul>
  <li>Boot to tape</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vax780 tboot.ini
/home/wsenn/workarea/retro/franz/work/tboot.ini-15&gt; at rp0 rp06.disk
%SIM-INFO: RP0: Creating new file: rp06.disk
/home/wsenn/workarea/retro/franz/work/tboot.ini-17&gt; at tu0 3bsd.tap
%SIM-INFO: TU0: Tape Image '3bsd.tap' scanned as SIMH format

HALT instruction, PC: 00050033 (HALT)
=
</code></pre></div></div>

<ul>
  <li>Restore Unix</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">=</code> is the tape’s minimal OS prompt. From here we will make a new filesystem on the rp06 and restor unix from the tape to the disk.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>=mkfs
file sys size: 7942
file system: hp(0,0)
isize = 5072
m/n = 3 500
=restor
Tape? ht(1,1)
Disk? hp(0,0)
Last chance before scribbling on disk. 
End of tape
=
</code></pre></div></div>

<p>Press enter after <code class="language-plaintext highlighter-rouge">Last chance before scribbling on disk.</code> to continue.</p>

<ul>
  <li>Restore <code class="language-plaintext highlighter-rouge">/usr</code></li>
</ul>

<p>Boot Unix, make a new fileystem for /usr, and restore it from tape.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>=boot

Boot
: hp(0,0)vmunix
61856+61008+70120 start 0x4B4
VM/UNIX (Berkeley Version 2.7) 2/10/80 
real mem  = 8323072
avail mem = 8062976
ERASE IS CONTROL-H!!!
# /etc/mkfs /dev/rrp0g 145673
isize = 65488
m/n = 3 500
# /etc/mount /dev/rp0g /usr
# cd /usr
# cp /dev/rmt5 /dev/null
# cp /dev/rmt5 /dev/null
# tar xbf 20 /dev/rmt1
# 
</code></pre></div></div>

<p>The restore can take a couple of minutes, be patient. The two lines:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># cp /dev/rmt5 /dev/null
# cp /dev/rmt5 /dev/null
</code></pre></div></div>

<p>Are just a way to get the tape device to fast forward to the tape file we want.</p>

<ul>
  <li>Cleanly shut unix down</li>
</ul>

<p>First we will sync and unmount any mounted devices, then we will sync our system. This is the “normal” way to shut down the unix environment in simh</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># sync
# sync
# sync
# cd /
# /etc/umount /dev/rp0g
# sync
# sync
# sync
# ^E
Simulation stopped, PC: 8000085F (BLBC 80010FA0,8000085F)
sim&gt; q
Goodbye
$
</code></pre></div></div>

<ul>
  <li>Backup the baseline system</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">tar cvzf rp06-baseline.tar.gz rp06.disk</code></p>

<h2 id="boot-the-system-and-run-franz-lisp">Boot the system and run Franz LISP</h2>

<ul>
  <li>Create a disk boot ini</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &lt;&lt;EOF &gt;dboot.ini
set tto 7b
set rq dis
set lpt dis
set rl dis
set hk dis
set rq dis
set rqb dis
set rqc dis
set rqd dis
set ry dis
set ts dis
set tq dis
set dz lines=8
set rp0 rp06
at rp0 rp06.disk
set tu0 te16
load -o boot3bsd 0
go 2
EOF
</code></pre></div></div>

<ul>
  <li>Boot to disk</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ vax780 dboot.ini

VAX 11/780 simulator Open SIMH V4.1-0 Current        simh git commit id: cf47a20f

Boot
: 
</code></pre></div></div>

<p>At the <code class="language-plaintext highlighter-rouge">:</code> prompt, provide the location of the kernel, <code class="language-plaintext highlighter-rouge">hp(0,0)vmunix</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>: hp(0,0)vmunix
61856+61008+70120 start 0x4B4
VM/UNIX (Berkeley Version 2.7) 2/10/80 
real mem  = 8323072
avail mem = 8062976
ERASE IS CONTROL-H!!!
# 
</code></pre></div></div>

<p>Change the root password. It needs to be at least 6 characters long.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># passwd root
New password:
Retype new password:
# 
</code></pre></div></div>

<p>To go into multi-user mode, press <code class="language-plaintext highlighter-rouge">^d</code>. this will allow you to login. Login as root with the new password.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#^D
Sat Aug 30 06:40:18 PDT 1980
entering rc
clearing mtab
mounting /usr on /dev/rp0g
preserving Ex temps and clearing /tmp
starting update
starting cron
leaving rc


Virtual VAX/UNIX (Ernie Co-vax)

login: root
Password:

Welcome to Virtual Vax/UNIX.
ERASE IS CONTROL-H!!!
#
</code></pre></div></div>

<ul>
  <li>Run Franz LISP Opus 32</li>
</ul>

<p>Run Franz in all of its 1979 glory! Type <code class="language-plaintext highlighter-rouge">(exit)</code> at the <code class="language-plaintext highlighter-rouge">-&gt;</code> prompt when you are ready to leave the lisp environment.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># lisp
Franz Lisp, Opus 32
-&gt; (+ 4 4)
8
-&gt; (car (cdr '(Hi there)))
there
-&gt;(exit)
#
</code></pre></div></div>

<ul>
  <li>Celebrate by backing up the working instance</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># sync
# sync
# sync
# ^E
Simulation stopped, PC: 8000085F (BLBC 80010FA0,8000085F)
sim&gt; q
Goodbye
$ tar cvzf rp06-working.tar.gz rp06.disk
rp06.disk
$ 
</code></pre></div></div>

<p>Now, anytime you want to run franz lisp, just reenter the directory with your dboot.ini and rp06.disk and type <code class="language-plaintext highlighter-rouge">vax780 dboot.ini</code>, boot the unix kernel, hit ^d at the prompt, and login as root with your new password!</p>

<p>Here’s a typical session:</p>

<p><img src="/assets/img/lisp/Terminal_004.png" alt="one" /></p>

<h2 id="creating-the-bootblock-from-uuencoded-sources">Creating the bootblock from uuencoded sources</h2>

<p>boot3bsd, the bootblock was created from Gunkies uuencoded source <a href="http://gunkies.org/wiki/3BSD_bootsector">http://gunkies.org/wiki/3BSD_bootsector</a>, using Gunkies uudecode program <a href="http://gunkies.org/wiki/Uudecode">http://gunkies.org/wiki/Uudecode</a>. Here is the process I followed to create the bootblock:</p>

<ul>
  <li>
    <p>Download uudecode source from above and save it as <code class="language-plaintext highlighter-rouge">uudecode.c</code>`.</p>
  </li>
  <li>
    <p>Download uuencoded bootblock from above and save it as <code class="language-plaintext highlighter-rouge">boot3bsd.uu</code></p>
  </li>
  <li>
    <p>Compile uudecode and use it to unencode the bootblock.</p>
  </li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cc -o uudecode uudecode.c
./uudecode boot3bsd.uu
</code></pre></div></div>
<p>Ignore the warnings, they’re irrevant to this process.</p>

<ul>
  <li>Confirm the result</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>shasum boot3bsd
482464bbd3ceb8ec9f02036ad06dbe5a181572e2  boot3bsd
</code></pre></div></div>

<p>That’s it.</p>

<p>Later - Will</p>

<p><em>post added 2023-07-31 11:55:00 -0600</em></p>


guid: https://decuser.github.io/lisp/2023/07/31/maclisp
title: MACLISP in ITS running on an emulated PDP-10
author: decuser
url: https://decuser.github.io/lisp/2023/07/31/maclisp.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/lisp/2023/07/31/maclisp.html
content_mime_type: text/html
content:
<p>This is a longer note that describes the process of getting ITS (Incompatible Timesharing System) up and running in order to run MACLISP. ITS is quite a large system and it has many different programming languages and programs available. In this note, we will only be using lisp and emacs, but future notes will explore logo, and perhaps other languages found in the distribution.</p>

<p><img src="/assets/img/lisp/Terminal_006.png" alt="one" /></p>

<!--more-->

<h2 id="resources">Resources</h2>

<ul>
  <li>
    <p><strong>The ITS operating system github repo</strong> <a href="https://github.com/PDP-10/its">https://github.com/PDP-10/its</a></p>
  </li>
  <li>
    <p><strong>The MACLISP manual</strong> <a href="http://www.maclisp.info/pitmanual">http://www.maclisp.info/pitmanual</a></p>
  </li>
  <li>
    <p><strong>OpenSIMH</strong> <a href="https://opensimh.org/">https://opensimh.org/</a></p>
  </li>
</ul>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Linux - I’m running Debian 12 (bookworm)</li>
  <li>A build environement (make, cc, and ld) - build-essential package on debian systems</li>
  <li>OpenSIMH - any reasonably recent version should work</li>
</ul>

<h2 id="getting-started">Getting Started</h2>

<ul>
  <li>Install some dependencies</li>
</ul>

<p>The pdp10-ka emulator requires - git, c compiler, make, expect, curses, autoconf, sdl2, sdl2-image, sdl2-net, gtk3. You will also need telnet and some network dependencies. Generally, whenever something complains about a missing dependency, google it and then <code class="language-plaintext highlighter-rouge">sudo apt install whatever</code>.</p>

<p>My own incanation was:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install -y bridge-utils build-essential expect gawk git libgtk-3-dev libpcap-dev libpcre3-dev ncurses-base ncurses-bin libncurses5-dev libpcap-dev libsdl2-2.0-0 libsdl2-dev libsdl2-image-dev libsdl2-net-dev make net-tools telnet uml-utilities
</code></pre></div></div>

<ul>
  <li>Create a Workarea</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/workarea/retro/its/{dist,work}
cd ~/workarea/retro/its/dist
</code></pre></div></div>

<ul>
  <li>Clone the ITS repository</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/PDP-10/its.git
</code></pre></div></div>

<ul>
  <li>Download a working system</li>
</ul>

<p>This will just take a few minutes. The repo can also be completely built from source, but that takes a long time (an hour or more).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd its
make download EMULATOR=pdp10-ka
</code></pre></div></div>

<h2 id="prepare-the-sytem-to-be-run">Prepare the sytem to be run</h2>

<ul>
  <li>Backup the original run file, so we can edit it</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cp out/pdp10-ka/run out/pdp10-ka/run.original
</code></pre></div></div>

<ul>
  <li>Edit the run file for no network to start</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vi out/pdp10-ka/run
# comment out lines dealing with imp
# set imp enabled
# set imp mac=e2:6c:84:1d:34:a3
# set imp ip=192.168.2.101/24
# set imp gw=172.31.1.100
# set imp host=10.3.0.6
# at imp tap:tap0
</code></pre></div></div>

<ul>
  <li>Create a back up of the untested baseline</li>
</ul>

<p>This is a good starting point. If you run into problems, you can revert to this baseline without having to redownload stuff.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ..
tar cvjf untested-baseline.tar.bz2 its/build/pdp10-ka its/start its/out its/tools/sims/BIN/pdp10-ka
</code></pre></div></div>

<ul>
  <li>Unpack the basline into work</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ../work
tar xvf ../dist/untested-baseline.tar.bz2
cd its
</code></pre></div></div>

<h2 id="run-its-the-first-time">Run ITS the first time</h2>

<ul>
  <li>Start the simulator</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./start
KA-10 simulator V4.0-0 Current        git commit id: 48186c90
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-22&gt; at -u tk 10000 speed=300
%SIM-INFO: Listening on port 10000
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-25&gt; at -u dpk 10002 speed=4800
%SIM-INFO: Listening on port 10002
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-26&gt; at -u dpk line=11,10019 speed=4800
%SIM-INFO: Line 11 Listening on port 10019
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-27&gt; at -u dpk line=15,10020 speed=4800
%SIM-INFO: Line 15 Listening on port 10020
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-29&gt; at -u mty 10003 speed=50000
%SIM-INFO: Listening on port 10003
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-30&gt; at -u mty line=9,10018 speed=9600
%SIM-INFO: Line 9 Listening on port 10018
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-31&gt; at -u mty line=8,10017 speed=9600
%SIM-INFO: Line 8 Listening on port 10017
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-32&gt; at -u mty line=7,10016;notelnet speed=50000
%SIM-INFO: Line 7 Listening on port 10016
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-33&gt; at -u mty line=6,10015 speed=9600
%SIM-INFO: Line 6 Listening on port 10015
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-35&gt; at ten11 10011
%SIM-INFO: Listening on port 10011
/home/wsenn/workarea/retro/its/work/its/out/pdp10-ka/run-37&gt; at auxcpu 10006
%SIM-INFO: Listening on port 10006

 DSKDMP
</code></pre></div></div>

<p>If all went well, nothing failed and you ITS prints DSKDMP in the terminal window.</p>

<ul>
  <li>Start ITS</li>
</ul>

<p>When DSKDMP is displayed, you can start ITS by typing <code class="language-plaintext highlighter-rouge">its&lt;CR&gt;&lt;ESC&gt;g</code> and it will start working. Ignore the NET message. We haven’t provided a working network, and won’t in this note. It isn’t needed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DSKDMP
its
$G
SALVAGER.317


IT IS NOW  3:25:48 PM EDT, MONDAY, JUL 31, 2023

KA ITS 1651 IN OPERATION AT 15:25:48
KA ITS 1651 SYSTEM JOB USING THIS CONSOLE.
TV 11 WENT DOWN -- 15:25:48
 LOGIN  TARAKA 0 15:25:49
TOP LEVEL INTERRUPT 200 DETACHED JOB # 4, USR:TARAKA CNAVRL 15:25:50
NET: TIMED OUT TRYING TO COME UP  15:25:58
IT IS NOW  3:26:17 PM EDT, MONDAY, JUL 31, 2023
 LOGIN  .BATCH 0 15:26:50
 LOGIN  GUNNER 0 15:27:50
</code></pre></div></div>

<h2 id="login-to-its-over-telnet-locally">Login to ITS over telnet (locally)</h2>

<ul>
  <li>Determine the port</li>
</ul>

<p>After the time is displayed, you can connect via telnet or login at the console itself. Let’s connect via telnet. Look up above to where the dpk is attached:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...&gt; at -u dpk 10002 speed=4800
%SIM-INFO: Listening on port 10002
</code></pre></div></div>

<ul>
  <li>Connect to the ITS sever using telnet</li>
</ul>

<p>That’s our telnet port, fire up telnet and connect:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 10002
Trying ::1...
Connected to localhost.
Escape character is '^]'.


Connected to the KA-10 simulator DPK device, line 0
</code></pre></div></div>

<ul>
  <li>Initiate a session</li>
</ul>

<p>To begin a session with ITS, press <code class="language-plaintext highlighter-rouge">C-z</code>, that is press and hold Ctrl and z at the same time. In this note anytime you see C-char, this is a control chord and works this way. If you see M-char, it means press Esc, let it go, then press the char. The ordinary Meta-char chord where you press Alt and char at the same time doesn’t seem to work. Alternatively and in the output a control chord may appear as ^char.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^Z
KA ITS.1651. DDT.1548.
TTY 21
You're all alone, Fair share = 99%
Welcome to ITS!

For brief information, type ?
For a list of colon commands, type :? and press Enter.
For the full info system, type :INFO and Enter.

Happy hacking!
</code></pre></div></div>

<ul>
  <li>Actually login to ITS</li>
</ul>

<p>And it’s ready for you to login. The system is not secure, which is a good thing. Sorta like when you live somewhere where you don’t have to lock the doors - hint, move outta the city… but still, lock the doors :).</p>

<p>So, to login we will use a : command, that is a command that begins with a colon. The command to login is <code class="language-plaintext highlighter-rouge">:login loginname</code>. Initials were in vogue back when, so I will use my initials:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:login wds
</code></pre></div></div>

<p>The system will respond with:</p>

<p><code class="language-plaintext highlighter-rouge">KA: WDS; WDS MAIL - NON-EXISTENT DIRECTORY</code></p>

<p>No worries, even though it complains about a non-existent directory, it’ll log you in anyway.</p>

<h2 id="first-steps">First Steps</h2>

<p>In this section we will set the terminal type, create a user directory and log out and back in so that ITS knows about the directory going forward. Otherwise, ITS will occasionally refuse to acknowledge the existence of the directory, usually at inopportune moments like when you are trying to save a ledit session.</p>

<ul>
  <li>Set the terminal type</li>
</ul>

<p>We need to tell ITS about our terminal (it may think we’re a line printer terminal ATM). The command needed here is <code class="language-plaintext highlighter-rouge">:tctyp AAA</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:tctyp AAA
:KILL
*
</code></pre></div></div>

<ul>
  <li>Create the user directory</li>
</ul>

<p>This is  a little tricky and a lot weird, but what we are going to do is type <code class="language-plaintext highlighter-rouge">&lt;C-r&gt;wds; ..new. (udir).&lt;CR&gt;</code> where <CR> is an actual carriage return. This will create a new directory named `wds`:</CR></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^R wds; ..new. (udir).
DSK: WDS; ..NEW. (UDIR) - FILE NOT FOUND
</code></pre></div></div>

<p>Ignore the FILE NOT FOUND error, it created the directory. To see this, change into the directory and type <code class="language-plaintext highlighter-rouge">C-f</code> to see the files, or just type <code class="language-plaintext highlighter-rouge">:listf wds;&lt;CR&gt;</code>. I’ll stop saying <code class="language-plaintext highlighter-rouge">&lt;CR&gt;</code> after : commands from this point forward, just know you need to end : commands with <code class="language-plaintext highlighter-rouge">&lt;CR&gt;</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:cwd wds
^F
KA   WDS
FREE BLOCKS #2=784 #3=1523 #0=568 #1=1541
*
</code></pre></div></div>

<ul>
  <li>Create a file in the directory to keep the salvager happy</li>
</ul>

<p>Apparently, there is a salvager that will get rid of empty directories. Let’s create a file in the directory. Let’s use emacs (this is a VERY early version, but should be quite familiar to any current emacs user). This version is a set of macros running in TECO, after RMS renamed it to EMACS, but before it became a standalone editor:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:emacs --read-- --me--
</code></pre></div></div>

<p>Yup, that’s exactly as typed, files have two names (somebody smarter than me knows why, just trust me for now). This file is called “–read–” and “–me–”. For me it’s easier to just think of it as a name and extension separated by a space instead of a ., but ymmv.</p>

<p>The screen should clear and emacs should fire up in all it’s ancient glory:</p>

<p><img src="/assets/img/lisp/Terminal_005.png" alt="two" /></p>

<p>Let’s enter <code class="language-plaintext highlighter-rouge">This file is to prevent directory salvage.</code>, Then type <code class="language-plaintext highlighter-rouge">C-x C-s</code> to save and <code class="language-plaintext highlighter-rouge">C-x C-c</code> to exit emacs. See, familiar, and easy right (says the :wq vi guy)? Then to list the file in the directory, type <code class="language-plaintext highlighter-rouge">C-f</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*^F
KA   WDS
FREE BLOCKS #2=784 #3=1523 #0=568 #1=1540
  2   --READ --ME-- 1 ! 7/31/2023 15:57:23
*
</code></pre></div></div>

<p>yay? I think so, and hopefully, you feel the same way.</p>

<ul>
  <li>Logout and back in again</li>
</ul>

<p>Let’s quickly logout and back in to get ITS to recognize our user directory properly:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:logout
KA ITS 1651  Console 21 Free. 16:32:00
</code></pre></div></div>

<p>and back in with <code class="language-plaintext highlighter-rouge">C-z</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^Z
KA ITS.1651. DDT.1548.
TTY 21
You're all alone, Fair share = 99%
Welcome to ITS!

For brief information, type ?
For a list of colon commands, type :? and press Enter.
For the full info system, type :INFO and Enter.

Happy hacking!
:login wds

To see system messages, do ":MSGS&lt;CR&gt;"
</code></pre></div></div>

<p>and set the terminal type:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tctyp AAA
:KILL
*
</code></pre></div></div>

<h2 id="program-in-maclisp">Program in MACLISP</h2>

<p>Let’s create some lisp and run MACLISP. This example uses emacs initially to create a lisp source file, then we run lisp standalone, load the file we created and use it’s function in our interpreter session. Then we will use ledit, a special mode of MACLISP using emacs from MACLISP on a special buffer.</p>

<ul>
  <li>Use emacs to create the file <code class="language-plaintext highlighter-rouge">addtwo lisp</code>:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:EMACS addtwo lisp

(defun addtwo (x y)
    (+ x y))
</code></pre></div></div>

<p>If you’ve been cutting and pasting as you followed along with the note, you might find that doesn’t work so great with emacs, so be careful. You may need to do it a line at a time. Anyway, enter the text, then <code class="language-plaintext highlighter-rouge">C-x C-s</code> and <code class="language-plaintext highlighter-rouge">C-x C-c</code>.</p>

<ul>
  <li>Run MACLISP</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*:LISP
LISP 2156
Alloc? n
*
</code></pre></div></div>

<p>We’re in! Let’s load our lisp file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(LOAD "addtwo lisp")
T
</code></pre></div></div>

<p>Lisp responds T if it was able to load. Let’s use it in our session:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(addtwo 5 3)
10
</code></pre></div></div>

<p>Sure 5+3 is 8, right? Ha, it’s base 8 (octal). Yes, you can change it, but it is running on a dec vm, so base 8 is just, right, right?</p>

<p>That’s it for this first session, let’s quit:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(quit)
:KILL  EMACS0$J
*
</code></pre></div></div>

<p><img src="/assets/img/lisp/Terminal_006.png" alt="one" /></p>

<p>yay again!</p>

<ul>
  <li>Use LEDIT in MACLISP</li>
</ul>

<p>Let’s use ledit now. Start lisp up again, and invoke (ledit) straightaway:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*:LISP
LISP 2156
Alloc? n
*
(ledit)
</code></pre></div></div>

<p>As soon as you type the closing parenthesis, emacs ledit will start up and your cursor will be top-left. The status line will display: <code class="language-plaintext highlighter-rouge">EMACS LEDIT (LISP)  Main:   *</code>:</p>

<p><img src="/assets/img/lisp/Terminal_007.png" alt="three" /></p>

<p>In ledit, let’s create the timestwo function:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(defun timestwo (x y)
  (* x y))
</code></pre></div></div>

<p>This time, we will use some ledit magic and not treat it as a normal emacs session. To push the defined funtion to the environment, press <code class="language-plaintext highlighter-rouge">M-z</code> (<ESC> let go, then 'z'), then to exit ledit and return to lisp, type `C-x z`.</ESC></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>;Reading from LEDIT
TIMESTWO
;Edit Completed

*
</code></pre></div></div>

<p>Let’s try it out in our lisp environment:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(timestwo 5 2)
12
</code></pre></div></div>

<p>Nice, and correct!</p>

<p>We can still load the existing lisp file and use it too:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(load "addtwo lisp")
(addtwo (timestwo 2 3) (timestwo 3 7))
33
</code></pre></div></div>

<p>Cool.</p>

<ul>
  <li>Exit LISP</li>
</ul>

<p>Let’s exit lisp:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(quit)
:KILL  LEDIT$J
*
</code></pre></div></div>

<p><img src="/assets/img/lisp/Terminal_008.png" alt="four" /></p>

<h2 id="shutdown-the-system">Shutdown the system</h2>

<p>To bring the system down, we will first logout out of our user account with <code class="language-plaintext highlighter-rouge">:logout</code>. Then we will <code class="language-plaintext highlighter-rouge">:login</code> with no user and proceed with a normal shutdown (if you don’t logout of the user account first, the shutdown will take 5 minutes).</p>

<ul>
  <li>Logout of the user account</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>* :logout

KA ITS 1651  Console 21 Free. 16:42:56
</code></pre></div></div>

<ul>
  <li>Login as an unnamed user</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^Z
KA ITS.1651. DDT.1548.
TTY 21
You're all alone, Fair share = 99%
Welcome to ITS!

For brief information, type ?
For a list of colon commands, type :? and press Enter.
For the full info system, type :INFO and Enter.

Happy hacking!
</code></pre></div></div>

<ul>
  <li>Initiate the shutdown</li>
</ul>

<p>First we initiate lock with <code class="language-plaintext highlighter-rouge">:lock</code>, then initiate the shutdown with <code class="language-plaintext highlighter-rouge">5down</code>, we will answer <code class="language-plaintext highlighter-rouge">Y</code> and <code class="language-plaintext highlighter-rouge">byeC-c</code>, to the prompts:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:lock
(Please Log In)
 LOCK.156
_5down
DO YOU REALLY WANT THE SYSTEM TO GO DOWN?
Y
___002 LOCK   SYS    DOWN   MAIL   WRITE

PLEASE ENTER A BRIEF MESSAGE TO USERS, ENDED BY ^C
bye^C

KA ITS 1651 NOT IN OPERATION 16:45:23
</code></pre></div></div>

<p>Since we are running in a telnet session, we can just end it. To exit telnet, press <code class="language-plaintext highlighter-rouge">^]</code> and at the telnet&gt; prompt, type <code class="language-plaintext highlighter-rouge">q</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^]
telnet&gt; q
Connection closed.
$
</code></pre></div></div>

<p>You can close the terminal and switch to the other terminal with our console session. You will see some console messages that are new and the last few should look like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SHUTDOWN COMPLETE
PI LEVEL 7 BUGDDT.  TYPE &lt;ALTMODE&gt;P TO CONTINUE.
YOU ARE NOW IN DDT.
BUGPC/   CAI COFFI4+1   $Q-2/   JRST COFFI7
</code></pre></div></div>

<p>At this point ITS is shut down. To exit, we will type <code class="language-plaintext highlighter-rouge">^\</code> to suspend the emulator and return to the sim&gt; prompt, then type <code class="language-plaintext highlighter-rouge">q</code> to exit the sim:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^\
Simulation stopped, PC: 773121 (CONSO 120,40)
sim&gt; q
Goodbye
$
</code></pre></div></div>

<h2 id="back-up-the-working-system">Back up the working system</h2>

<p>It is a really good idea to back up the tested working system. This way, you can always get back to what worked with minimal fuss:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd ../../dist
tar cvjf tested-working.tar.bz2 its/build/pdp10-ka its/start its/out its/tools/sims/BIN/pdp10-ka
</code></pre></div></div>

<p>That’s it for now. In another note, I will walk through setting up networking and using LOGO in ITS with a graphical terminal and turtle.</p>

<p>Let me know if you run into any issues.</p>

<p>Later, Will</p>

<p><em>post added 2023-07-31 18:07:00 -0600</em></p>


guid: https://decuser.github.io/geometry/2023/12/19/thunderbird-hangs-indexing
title: Geometry Explorations
author: decuser
url: https://decuser.github.io/geometry/2023/12/19/thunderbird-hangs-indexing.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/geometry/2023/12/19/thunderbird-hangs-indexing.html
content_mime_type: text/html
content:
<p>This note describes a method for fixing Thunderbird when it hangs while indexing.</p>

<p>I’m posting this in case it’s useful to folks and for my own reference. It took me a quite a while to figure it out.</p>

<p>So you have been using Thunderbird for your email for a while, on Windows, Linux, Mac, FreeBSD, and so on, for let’s say a couple of decades. If you copy your profile around much, you are bound to hit an indexing issue where Thunderbird is unable to index your archives. You open up Activity Manager and it helpfully reports:</p>

<p>Indexing 32 of 14243 messages in Archives/2002-2020/2016</p>

<p>Read on for the fix.
<!--more--></p>

<p>You watch the Activity Manager for a while, mesmerized perhaps by it’s stolid refusal to progress or go away. Then you fire up your favorite search engine and start looking for answers. If you’re lucky, this page pops up, otherwise you read drivel like “try again”, “delete your index and rebuild it”, or even reinstall.</p>

<p>If you’re on linux, or another unix that has similar functionality, you can do this!</p>

<p>In a terminal:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>strace  thunderbird
</code></pre></div></div>

<p>In thunderbird:
open Tools-&gt;Activity Manager</p>

<p>When it gets to the place where it hangs, in the terminal, press CTRL-C to end the session. Capture the output from the terminal window into a text editor and search from the bottom up for the directory it’s complaining about. In the above example, look for the last occurance of 2016/. The trailing slash is important to include in your search to find the correct information.</p>

<p>In my strace output, the last occurance(s) are:</p>

<p>access(“/home/wsenn/Thunderbird/Mail/Local Folders-maildir/Archives.sbd/2002-2020.sbd/2016/cur”, F_OK) = 0
openat(AT_FDCWD, “/home/wsenn/Thunderbird/Mail/Local Folders-maildir/Archives.sbd/2002-2020.sbd/2016/cur/1723773452464.eml”, O_RDONLY) = 147</p>

<p>This is likely (so far, it’s always, but time may tell if there are exceptions) the file that’s breaking the indexing. Move it off somewhere to review:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir -p ~/Desktop/2016
mv "/home/wsenn/Thunderbird/Mail/Local Folders-maildir/Archives.sbd/2002-2020.sbd/2016/cur/1723773452464.eml" ~/Desktop/2016/
</code></pre></div></div>

<p>Restart thunderbird without strace and pull up activity manager to see if it continues. If so, rinse and repeat as needed.</p>

<p>– will</p>

<p><em>post added 2024-08-16 10:27:00 -0600</em></p>


guid: https://decuser.github.io/geometry/2023/12/19/geometry-explorations
title: Geometry Explorations
author: decuser
url: https://decuser.github.io/geometry/2023/12/19/geometry-explorations.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/geometry/2023/12/19/geometry-explorations.html
content_mime_type: text/html
content:
<p>This note sets up a series of related notes pertaining to my explorations in Geometry and by extension, Maths.</p>

<p>The explorations are my work in trying to make sense of the world through math. They are presented here, in part, to motivate me to express my thoughts in a more organized fashion than I might otherwise, and in part to share in the hopes that some small few might benefit or wish to chat about things.</p>

<p>So, enjoy and if you do, feel free to email me about it.</p>

<!--more-->

<p>The notes to come are not mathematical treatises, they are mostly me trying to figure stuff out. I expect they will be superseded with more intelligible writings as I learn more, but they are not definitive. They are more like a journal where I lay out my thoughts of the moment.</p>

<p>I have always found math confusing and so much of it lacking comprehensibility or cohesion. When I came across Geometry, as part of my personal remediation plan doing Saxon Math, begun about 7 years ago. I was stunned to find something that actually made sense, was coherent and cohesive. It turns out that Euclid, writer of the Elements of Geometry, established by example, one of the greatest models of thought that the world has ever known. I dug in to his subject, Geometry, and I dug in hard. I worked through propositions referenced by Saxon, in the Elements. I was mesmerized, but not at first. At first, it seemed incredibly difficult to understand, but after many, many hours of work and contemplation, it clicked and I got it… even if I couldn’t apply it in novel circumstances without great difficulty on the drop of a dime. But, I felt like I could see where it was coming from and where it was going. Thank you Euclid and thank you John Saxon for introducing me to the subject in such an accessible way.</p>

<p>Before I dive into the explorations, I feel compelled to defend Euclid, who while appreciated by many, is mocked unfairly at times by folks. Euclid’s postulates are not complete. He made some assumptions that people eventually decided were unwarranted. He didn’t prove every case of every postulate. Other geometries are possible and valid. So what? Euclid wrote a work of mathematics that lives as the finest example of mathematics ever written (to date). He didn’t write a book on how to write axiomatically, or how to write with rigor. If he had, things would have been quite different. Rather, he showed the world, by example, how to write a book with axioms and rigor, that would stand as the eminent example of how to do so, for the better part of two and a half millennia.</p>

<p>I find it amusing and bemusing that folks spend vast amounts of time and energy learning Euclid’s work, only to turn around and smugly criticize its flaws. To my mind they are like children who want to show their independence from their parents - meanwhile, everyone can see by looking that they are their parent’s children. In a similar vein, modernists from David Hilbert to Bertrand Russell, while widely criticizing Euclid, so clearly resemble their forbear, that it beggars belief. Its shocking to me that they wouldn’t simply correct the flaws inherent in his work (as an exemplar of a mindset) and extend it, without bad-mouthing it. These geniuses, and geniuses they so clearly are, have not, with all there labor achieved a work as influential as the work attributed to Euclid.</p>

<p>Anyway, enough ranting, off to explore :).</p>

<p>– will</p>

<p><em>post added 2023-12-19 12:27:00 -0600</em></p>


guid: https://decuser.github.io/geometry/2023/12/19/wills-geometry
title: Will’s Geometry - A Setting Out.
author: decuser
url: https://decuser.github.io/geometry/2023/12/19/wills-geometry.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/geometry/2023/12/19/wills-geometry.html
content_mime_type: text/html
content:
<p>This is a note where I begin to develop my own geometry based on the example of Euclid, but with an eye towards addressing its shortcomings - what hubris?! But seriously, I’m pretty sure my geometry will pale in comparison. The purpose of the exploration is not to show off, but to learn more about the world and in this regard, will be interesting and educational.</p>

<!--more-->

<p>Gotta start somewhere!</p>

<p>Start from first principles - the evidents.</p>

<p>Shapes exist and are perceived. That is, we see and describe the world around us in abstract terms and shapes are abstract. As we abstract away details and try to describe things that exist, we highlight some things / aspects of things, and disregard others. We strive to arrive at useful ways of referring to groups of / sets of objects. Geometry, which started as a way of measuring land, has evolved into an ever-abstracting study of shape. What is shape? Wow, so hard to establish the bare necessities. Maybe a shape is a collection of points? What is a collection and what is a point?</p>

<p>Let’s just say (posit) that a collection is just what it sounds like, one or more than one of something, or nothing at all (for convenience, later). In this case, a collection of points. A point being the idea of the smallest thing (or not thing), imaginable. We represent this idea generally with a dot drawn on a page. Keep in mind that a point is an idea and doesn’t have width, height, or any physical measure, whereas the dot does.</p>

<p>Maybe think of the dot as a graph (physical representative) of the point and imagine zooming in on the dot, imagine it never changing in appearance, whereas the area around it expands, endlessly.</p>

<p>We have our first postulates:</p>

<ul>
  <li>a point is an idea that can be represented by a dot. It has no measure.</li>
  <li>a collection (set) is a collection of zero or more points.</li>
</ul>

<p>What can we do with our postulates? Not much, at this “point” :). We can put points into a collection and take them out again. We can imagine that our collection, thus created, refers to different points. But, if a point has no measure, or other attribute, how can two be different?</p>

<p>Now we can posit something new about points, relationship. Points can be different. If they are different, they cannot be the same point :). This is an intuition related to the nature of information - any difference that makes a difference to a knowing subject. But again, how are they different? We are in desperate need of a property or aspect of points with which to differentiate them. Naming them provides one basis - we can call our points by name. Let’s say A is one of our imaginary points and B is another - difference! But, that’s of limited utility in the context of shapes, so we look for another. How about location. Wow! That “maps” to our intuition pretty well, points are located. What this means will be expanded on, but for now, just know that location simply means that point A is not in the same place as B, there is difference. In space, this would mean that points A and B do not occupy the same space, and that’s reasonable and seems consistent with reality, but in this case we are only suggesting that A and B are different and that difference is location.</p>

<p>This brings us to our next postulate:</p>

<ul>
  <li>location - objects (in our world, there are collections and points only) have difference.</li>
</ul>

<p>Location is tricky to describe, but I mean that points are located (have difference) somewhere, even if its only in our mental world. We will represent our idea by referring to the idea of physical space, in the real world, that is the 3 dimensions we normally consider space.</p>

<p>How are points related locationally (is that even a word)? Suppose that points can be next to each other. Indeed, if two points exist (even in the mind), in order for them to be different, by definition (see above), they have different locations and one is next to the other (if is isn’t clear, then here they are so defined, as being next to each other).</p>

<p>The hard part comes when we add a third point. Where are the points in relation to each other. If points have no measure, then why can’t they all be next to each other? If they are all next to each other, then they can’t not be next to each other, right? But, we know this isn’t how the real world works, things can be between each other… ick, so hard to explain betweeness. Why? Well, if a point has no measure, then it can’t be put between two points. Unless, perhaps, we establish the idea that there is order on the universe. Let’s do that. The universe is ordered, so mote it be. If that’s the case, then we have another postulate:</p>

<ul>
  <li>order - the universe has order</li>
</ul>

<p>That is, one thing can be said to be ordered (precede, or follow) with respect to another. Order is imposed, so, without knowing the established order, one can only detect it and not know what the origin or orientation of that order is in its entirety.</p>

<p>Now, betweeness becomes evident as the established order of three objects (points). We say, determine, decree, demand, etc. that a point is between two others. This may sound silly and needlessly complex, but it is what it is and betweeness is our next postulate:</p>

<ul>
  <li>betweeness - the property of a point that indicates it precedes a particular point and follows another particular point</li>
</ul>

<p>Now we can speak about dimensionality. We can define dimensions thusly, a single dimension exists when a point is brought into existence. Another, the second dimension, when three points are realized. Why three and not two, well, I’m not sure, with two points we can speak about the relationship between the points, A is not B, B is not A, A exists, B exists, A and B exist, but that’s pretty much it. In order to go further, we really need at least 3 points (this is an exploration of the mind, not definitive). With three points, we can say much, much more. We can say is everything we can say about two, plus some more.</p>

<p>Let’s say that A and B and C are points in our universe. A is next to B and B is next to C, but C is not next to A. Then, B is between A and C.</p>

<p>Here’s a thought exercise to be integrated into the discussion as it is determined where it should go…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Think of a light filled universe.

Bring a point, A, into existence. If the point had measure, and the light had a source, this would change the universe in a measurable way, as it stands this is not the case. It just is.

Bring another point B, into existence. No change... or is there? There is difference, but not measurable.

Bring a third point C, into existence, such that we say B is between A and C. Again, difference, but not measurable. Why not? Because points have no measure!

But when we bring our points into the real world, and of necessity given them measure, voila! There's going to be measurable differences. But, very local. Perspective is hinted at here - we need it in order to appreciate our new universe. If we were to place our consciousness at a point and look, as it were, around, what would we "see". If we were at A, we would see B, if we were at C, we could also see B, but from A, we could not see C and from C we could not see A. Wow!
</code></pre></div></div>

<p>But, for now, we’re sticking with betweeness being nothing more than established by fiat and being definitional in nature. B is between A and C because I say it is and beyond establishing order between A, B, C, has no material effect on anything.</p>

<p>Ah, but let’s give another name to that order of points and introduce another postulate:</p>

<ul>
  <li>line - a line is an ordered set of points</li>
</ul>

<p>But, it’s tricky again, the line may be a set of points, but surely, we can’t refer to a line by it’s points, that’s nuts. So, we’ll say that a line can be named by any two points, belonging to the set, where the set established the order. Line AB therefore is part of ABC. As is AC and BC.</p>

<p>Let’s say that the order we write the points matches their ordering, this means AB is not the same ordering as BA, and ABC means that B is between A and C, with A preceding and C following.</p>

<p>To recap what we have so far:</p>

<ul>
  <li>point</li>
  <li>collection</li>
  <li>location (difference)</li>
  <li>order</li>
  <li>betweeness</li>
  <li>line</li>
</ul>

<p>The point is fairly standard to think about in this way, collection or set is what we would expect, location is a bit different :),, order is meta, betweeness is necessary, but I’m no geometry expert, so I could be naive on this. Line is way different from what it is usually described as, but this is because I’m working through it from the ground up.</p>

<p>… enough for today. Too many gaps, too many doubts, need to consider for a bit :).</p>

<p>– will</p>

<p><em>post edited 2023-12-19 13:58:00 -0600</em></p>


guid: https://decuser.github.io/unix/research-unix/v7/2024/05/23/research-unix-v7-3.2
title: Research Unix Version 7 - 3.2
author: decuser
url: https://decuser.github.io/unix/research-unix/v7/2024/05/23/research-unix-v7-3.2.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/unix/research-unix/v7/2024/05/23/research-unix-v7-3.2.html
content_mime_type: text/html
content:
<p>This is an updated note that covers building a working v7 instance from tape files that will run in the OpenSImH emulator. First, the reader is led through the restoration of a pristine v7 instance from tape to disk. Next, the reader is led through adding a regular user and making the system multi-user capable. Then, the reader is shown how to make the system multi-session cable to allow multiple simultaneous sessions. Finally, the system is put to use with hello world, DMR style, and the learn system is enabled.</p>

<p>The note explains each step of the process in detail.</p>

<!--more-->

<p>Last Updated May 23, 2024</p>

<h3 id="changes-since-revision-31">Changes since revision 3.1</h3>

<p>Revision 3.2 - minor revision:</p>

<ul>
  <li>Tape format issue fixed in mktape.pl and mktape.py, resulted in updated image on tuhs.</li>
  <li>Updated note for Linux Mint 21.3 “Virginia” host and latest Open-SIMH</li>
</ul>

<p>Here’s the note, as a pdf:</p>

<iframe allow="autoplay" height="480" src="https://drive.google.com/file/d/1eGrdZVc2R-hFfsbJ70PNbWBGNEXCLN1W/preview" width="640"></iframe>

<p>Local copy here: <a href="/assets/pdf/unix/research-unix-7-pdp11-45-3.2.pdf">research-unix-7-pdp11-45-3.2.pdf</a>
<!--more--></p>

<p><em>post added 2024-05-23 08:00:00 -0600</em></p>


guid: https://decuser.github.io/linux/2024/09/23/github-actions
title: github actions - seriously?
author: decuser
url: https://decuser.github.io/linux/2024/09/23/github-actions.html
feedurl: https://decuser.github.io/feed.xml
base: https://decuser.github.io/linux/2024/09/23/github-actions.html
content_mime_type: text/html
content:
<p>This post is not a particularly informative one, but when I tried to switch to github actions for publishing the blog, uh, it went poorly.</p>

<p>Maybe I’ll try again later, but for the time being - sticking with publish a branch.</p>

<p>If you’re lost reading this, no worries. It’s github speak for if it ain’t broke, don’t fix it :).</p>

<p><em>post added 2024-09-23 19:12:00 -0600</em></p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/03/high-trust-society
title: High Trust Society
url: https://geohot.github.io//blog/jekyll/update/2024/11/03/high-trust-society.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/03/high-trust-society.html
content_mime_type: text/html
content:
<blockquote>
  <p>I just want you to see, I just want you to see<br />
The way we drag a bunch of people into lunacy<br />
  – mos thoser</p>
</blockquote>

<p><img src="/blog/assets/images/public-trust-in-government.png" alt="image" /></p>

<p>Regardless of who wins on Tuesday, does anyone think this gets fixed? Is Kamala going to restore trust in government? Is Trump going to restore trust in government?</p>

<p><img src="/blog/assets/images/trust_in_gov_worldwide.jpg" alt="image" /></p>

<p>Despite what Western media might have you believe about how the people in China are lying cause they are scared or something, these stats reflect what I have seen. I trust the Chinese government more than I trust the US government.</p>

<p>It’s obvious on the streets. These aren’t scared people obeying out of fear, these are people playing their role with pride to live in a nice society. I feel the American sneer just writing those words, but it doesn’t make it less true.</p>

<p><img src="/blog/assets/images/china_power.jpg" alt="image" /></p>

<p>GDP can be manipulated ten ways till Sunday, electricity and steel production are much harder to fake. A government delivering growth and better lives to people is one worth trusting. A government that <a href="https://apnews.com/article/new-york-pet-squirrel-seized-peanut-pnut-c2baa345d9e76416e0ca6d6e947ee272">kills squirrels</a> that get too famous on social media, not as much. I’ll note that <a href="https://en.wikipedia.org/wiki/Abortion_in_China">social issues</a> are well handled in China too.</p>

<p>When Americans are asked about this, they will defend some nebulous concept of freedom, and I ask, freedom to what? Vote? Freedom from what? People taking your stuff? Here’s a guy trying to steal a bike from the comma office last week.</p>

<p><img src="/blog/assets/images/bike_thief.png" alt="image" /></p>

<p>Guess the police were too busy killing squirrels. Of course, had I confronted the guy, the police would have been quick to come for me. Anarcho-tyranny.</p>

<hr />
<p><br /></p>

<p>When a society loses trust, it takes a lot for it to come back. Many people in America aren’t in agreement on basic things, that growth is good and crime should be illegal. What would it take to change their minds?</p>

<p><img src="/blog/assets/images/out-of-wedlock.png" alt="image" /></p>

<p>The answer may be nothing short of generational change or civil war. Regardless, it won’t be a quick process. As much as I might side with Elon and like what he is doing, most of the country won’t. Many of my friends are Kamala voters, and their answer to Trump voters is to perhaps to “accept their diminished place in a rapidly changing world.” The Trump voter answer to Kamala voters is something equally racist and sexist, maybe uhh, there’s sort of a reason the people who built everything are the people who built everything.</p>

<p>None of this fixes trust in society. None of this brings you closer with your neighbor. It will take either generational change with a new set of politics, or a civil war and the reconstruction that follows. Neither of which I really care to be around for. To me the synthesis is obvious, but it’s like the country is going through a mental health episode and you can’t just tell people what’s wrong with them in the first therapy session, they have to go through a painfully long process (billed to medicare, don’t worry lah) to discover it themselves.</p>

<hr />
<p><br /></p>

<p>So where does that leave us? Facts are easy, figuring out actions is hard. China is a society for the Chinese, and I am not Chinese. Hong Kong, Singapore, and Dubai are nice (and multicultural), but they aren’t large markets.</p>

<p>I think the future is the Internet. The American empire is over, the Chinese empire is next, and <a href="https://thenetworkstate.com/">the Internet</a> is the empire after that. We build for that world.</p>

<p>Back to work. <a href="https://tinygrad.org/">tiny corp</a> is a remote first company, and we are hiring. I trust that the tools to manage remote companies will get rapidly better with AI in the next 5 years (think automated PMs and ops).</p>

<p>Oh and in the IRL mean time, it’s very nice to be physically in a high trust society. Still working on opening an office in Hong Kong for those who want, salaries higher in person.</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/04/influence-agents
title: Influence Agents
url: https://geohot.github.io//blog/jekyll/update/2024/11/04/influence-agents.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/04/influence-agents.html
content_mime_type: text/html
content:
<blockquote>
  <p>Check 1, 2 is the mic on?<br />
Check on you, is the vibe off?<br />
  – Thos Moser</p>
</blockquote>

<p>Most AI doom scenarios are nonsense. The idea of a rogue computer behaving in a way no humans want never made sense to me, only to Hollywood who doesn’t know all that much about computers.</p>

<p>Paul Christiano has one of my <a href="https://www.alignmentforum.org/posts/CoZhXrhpQxpy9xw9y/where-i-agree-and-disagree-with-eliezer">favorite takes</a>, that the creation of AI will look a lot less like a visit from an alien produced by natural selection (where you are most certainly dead), and a lot more like animal breeding.</p>

<hr />
<p><br /></p>

<p>That out of the way, what is going to happen? Let’s follow out a trend.</p>

<p>A lot of the story of the last 50 years is the story of advertising. And it’s crazier than you think, Instagram makes <a href="https://www.answeriq.com/instagram-ad-revenue/">$39.7B</a> US revenue off of 169M people, which is $234 per person, or $119 per person <em>including those who don’t use Instagram</em>.</p>

<p>Google’s revenue is <a href="https://www.coolest-gadgets.com/google-statistics">$305.6B</a>, 47% from the US, so $428 per person.</p>

<p>For each of the 334M US people, you could make a pie chart of both their spend and their time.</p>

<hr />
<p><br /></p>

<p>Curtis has a saying, which I’ll paraphrase. Power doesn’t stop at the voter, it just flows through the voter. The 2024 election had <a href="https://www.opensecrets.org/news/2024/10/total-2024-election-spending-projected-to-exceed-previous-record/">$15.9B</a> spent on it, so $48/person, $98/voter, and way more if you only count only the people in swing states.</p>

<p>How much spend would it take to change your vote? Okay, that’s too much to consider. How about, how much spend would it take to get you to change dish soap? Go to a different coffee shop?</p>

<p>The marketplace for your behavior is ever increasing in scope.</p>

<hr />
<p><br /></p>

<p>Now let’s introduce AI. Whenever I think about AI, I think about analogies to people.</p>

<p>Currently, while ads are becoming more and more targeted, this isn’t anywhere close to its limit. Imagine a room of 10 CIA agents running at 1000x real time (they have 16 hours for each minute of yours). And their only job is to influence you.</p>

<p>They aren’t stupid. They know not to bombard you with crap. They have studied your behavior for the last 10 years. They know exactly what it takes to make you actually change your mind. They know what you respond to. There’s no infighting among them, they are all perfectly aligned with the goal of altering your behavior.</p>

<p>They have studied marketing. They have studied psychology. They know more about you than you know about yourself. They will make sophisticated ad campaigns in real time only to ever be consumed by <b>you</b>. The endgame of targeted advertising.</p>

<p>The only reason you don’t have 10 agents doing this right now is that you aren’t worth it. But as the cost of these influence agents falls, this will be the future. This is what Meta and Google are building, even if they aren’t fully aware of that yet.</p>

<hr />
<p><br /></p>

<p>A team of long running extremely competent people with the sole goal of manipulating you.</p>

<p>You don’t stand a chance.</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/06/what-is-possible
title: …and now we see what is possible
url: https://geohot.github.io//blog/jekyll/update/2024/11/06/what-is-possible.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/06/what-is-possible.html
content_mime_type: text/html
content:
<p>Every 70 years America goes through a revolutionary transition. Washington, Lincoln, FDR, now?</p>

<p>The Republicans now control the Presidency, the House, the Senate, and the Supreme Court. Is that everything? Does government power lie there, like we are told, or is it all secretly elsewhere? This is likely the best chance we’ll get to find out.</p>

<hr />
<p><br /></p>

<p>In retrospect, I’m very impressed with how Elon did the Twitter transition, and I’m grateful to have had a front row seat to that history. It made me reconsider how power works. He has an army of competent lieutenants, and he tasked them with doing a variety of things.</p>

<p>I regret not seriously trying to fix search, I didn’t really understand at the time what he was asking or why. I thought I was there to reverse engineer the mess of a codebase, while in reality just having people try to build features and seeing what breaks is a better strategy. I’m not very good at being a follower, I need to deeply understand why, and I’m sorry I didn’t until later.</p>

<p>I am much more conservative, whereas he seems to operate at the edge of leverage. Just look at how he went all in on this election. This is something I struggle with with respect to my own comparative lack of success. I am not all that open to risk, even when the downside isn’t close to life ending. While I believe very strongly in my ability to use a process and make continuous forward progress, it’s a slow process. I want to take more risk, but when I think it through my ideas for risk often just feel foolish.</p>

<hr />
<p><br /></p>

<p>I really hope Donald Trump understands the need for radical change of the US government (on the order of firing 80% of the people), and also understands that he can’t do it without Elon’s help. So that’s obstacle one, does Elon get free range to operate?</p>

<p>Even if so, this isn’t Twitter, and it may not work. I frequently think about if it’s possible to shut Google down, like does anyone have the ability to do this? Twitter was in a position where it could be purchased, no one is rich enough to buy Google. You could get a coalition of capital, but <em>could you?</em></p>

<p>If you can’t shut it down, you don’t control it. While Elon could have shut down Twitter, can control of all three branches of government shut down the government? I’m not sure. And if not, where is the power actually?</p>

<hr />
<p><br /></p>

<p>It’s possible this will be another completely boring presidency. Stupid squabbles over normal stupid American Overton window things, and the same trillions of dollars going to the same people, just slightly more red.</p>

<p>It’s even possible that the Intelligence Agency Deep State shows up on your first day in the Oval Office, tells you who really runs things, and tells you what happens to you if you defy them. “Hello, we are the Deep State. Here are the bounds in which you can act. Step outside them, and we will kill you”</p>

<p>Which is another place the government differs from Twitter. As a state, they have a legitimate monopoly on violence, so is the deep state’s threat even wrong? “You just didn’t understand the President hasn’t actually been in charge for 60 years. Better for everyone that way. We have control of weapons that can end the world. We can’t trust something like that to <em>the will of the people</em>”</p>

<hr />
<p><br /></p>

<p>I’m not sure anyone really knows the answers to these questions. But if the Trump transition team reads this, I’d really really like to find out. The USGOV Files?</p>

<p>Will this be one of the historical once every 70 years administrations? I’ll know it is if the government budget is cut by over 50%. That shows you actually have power, and only then is it possible to make a new, good, government.</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/13/collective-marshmallow-test
title: The Collective Marshmallow Test
url: https://geohot.github.io//blog/jekyll/update/2024/11/13/collective-marshmallow-test.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/13/collective-marshmallow-test.html
content_mime_type: text/html
content:
<p>Society is even harder than passing <a href="https://en.wikipedia.org/wiki/Stanford_marshmallow_experiment">the marshmallow test</a>.</p>

<p>Instead of a single person, imagine 100 people in a room. One marshmallow is placed on a table. If everyone can leave it alone for 15 minutes, everyone gets 2 marshmallows. But if just one person eats it, everyone gets nothing (except for the guy who ate a marshmallow, he got that marshmallow).</p>

<p>You think we’d pass? &lt;insert TikTok link to a guy eating the marshmallow and laughing&gt; You need mechanisms like shame to pass, and our culture has done away with them.</p>

<hr />
<p><br /></p>

<p>The post-election glee has worn off, and while it’s so nice culturally to have a complete and resounding defeat of wokeism, the underlying issues won’t go away. Trump is no <a href="https://en.wikipedia.org/wiki/Javier_Milei">Milei</a>, he’s a guy who declared bankruptcy four times. (though compared to the Harris campaign spending…wow it really could have been so much worse)</p>

<p>Wokeism appeals to people who have not exceeded their parents economically. In order to justify that they have moved up in the world, they cling to a cult of moral superiority. While their parents owned a house, they know that the land that house was built on was stolen from the Lenni-Lenape First People’s tribe. It’s a fancy form of the <a href="https://read.gov/aesop/005.html">sour grapes</a> story.</p>

<p>I think the problem is something like this. In a fair economy, Americans have expectations exceeding their market value. They don’t see a way to meet these expectations, so they reject the system.</p>

<hr />
<p><br /></p>

<p>I don’t want to become a <a href="https://en.wikipedia.org/wiki/J._D._Salinger">hermit</a>, but I feel very distant from the modern hustle and hypergambling culture. The overheard conversations in coffee shops in Hong Kong have started to trigger me, “advisors and finance influencers” can fuck off to hell. I’m a 3 hour flight from <a href="https://devcon.org/en/">Devcon</a>, but I’m not sure I can tolerate crypto culture anymore. I’ve been feeling isolated.</p>

<p>At first I was thinking about how hyperinflation would fix this, but I’m not sure it would cause the rich to lose. With nothing else to do all day they would see it coming. Basically everything screws the middle class, the only class that produces value in society (the poor don’t do shit and the rich have their money making money instead of working). Can’t steal from the poor cause they don’t have things, and can’t steal from the rich cause lol…we’re the rich. Have to take from the ever diminishing middle class, since they are the only ones who work.</p>

<hr />
<p><br /></p>

<p>I guess I’m basically saying we have to redistribute the wealth, however, the government is the absolute last group of people I’d ever trust to do this. I don’t trust the wealth redistribution in crypto either, the current rich have had too much time to adjust and the biggest morons I know are now saying blockchain.</p>

<p>How do we set up a society such that wealth flows to the productive? It seems so distant from what we have now. This probably happens over a long time horizon regardless, but it’s so frustrating hearing what people’s values are. Money isn’t real! It’s not the territory, it’s the map! And changing the map doesn’t change the territory, it just makes the map shittier up to the point nobody trusts it.</p>

<hr />
<p><br /></p>

<p>Of course, attaching yourself to the outcome of grand projects is <a href="https://www.amazon.com/How-Found-Freedom-Unfree-World/dp/0965603679">no way to be happy</a>. I wish there was still a <a href="https://static.wikia.nocookie.net/bojackhorseman/images/5/5f/Wesleyanuniversity.png/revision/latest/scale-to-width-down/1000?cb=20200117133435">retreat in academia</a>, I don’t want to participate in this shit. Back to slow and steady progress on <a href="https://github.com/tinygrad/tinygrad">tinygrad</a>.</p>

<p>(btw, I find it funny that people say I don’t stick to things. how many self driving car companies are even still around? <a href="https://comma.ai/">comma</a> has been around for 9 and growing each year. and been working on tinygrad for over 4 years almost every day, see my github for proof. what have you done?)</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/17/a-one-way-bridge
title: A One Way Bridge
url: https://geohot.github.io//blog/jekyll/update/2024/11/17/a-one-way-bridge.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/17/a-one-way-bridge.html
content_mime_type: text/html
content:
<p>Okay I went to Devcon. And while there I had a great idea that the crypto space really needs. It seems like while AI infrastructure has improved by leaps and bounds in the last 5 years, crypto infra has actually gotten worse. I’m proposing some great new infrastructure that the crypto space deserves.</p>

<hr />
<p><br /></p>

<p>We still don’t have a good decentralized bridge between Bitcoin and Ethereum, and with the rising price of Bitcoin this is more important than ever. I have <a href="https://github.com/cheapETH/bridge">some experience building bridges</a>, so I’m proposing one. However, unlike most bridges, this is a one way bridge. It works like this:</p>

<ol>
  <li>Send Bitcoin to 3bridgebridgebridgebridgebridge</li>
  <li>Wait for several block confirmations</li>
  <li>Prove inclusion of your send in the Bitcoin chain to the bridge</li>
  <li>Receive BBTC (Bridged BTC) tokens on Ethereum of the amount sent</li>
</ol>

<p>I’ll note, nobody has the private key to 3bridgebridgebridgebridgebridge, so there is no way to recover your original Bitcoin. That’s okay, they have been safely bridged to Ethereum and you have received your BBTC token.</p>

<p>If you’d just like to buy exposure to Bitcoin on Ethereum without using the bridge, you can buy the BBTC token on any DEX.</p>

<hr />
<p><br /></p>

<p>Is it really that simple? Answer: yes, but only if people believe it is.</p>

<p>You can’t really believe the BBTC token is worth 0, can you?</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/20/a-place-for-me
title: A Place for Me
url: https://geohot.github.io//blog/jekyll/update/2024/11/20/a-place-for-me.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/20/a-place-for-me.html
content_mime_type: text/html
content:
<p>Have all the jobs been fake for years? <a href="https://www.researchgate.net/publication/234554226_On_Self-Licking_Ice_Cream_Cones">Read this</a>, a NASA critique from 1992.</p>

<p>Basically society is run by useless people making work for other useless people so that together they can all alleviate their deep concern about not having a place in society.</p>

<hr />
<p><br /></p>

<p>Elon has a bigger tent of types of people that can help on his mission than I do, and even that tent is too small to include most people. I think that’s the deep reason for the Elon haters, it’s that they don’t see their place in his society.</p>

<p>I lashed out at a fan in Bangkok, when he told me his friend was a fan of mine, I replied with “why do I care?” I was already in a bad mood, normally I’d be nicer and if you read this sorry it was directed at you, but I do sort of stand by the point. Low commitment from lots of people is useless. I’m not going to milk you for merch sales.</p>

<p>By the way, if you ever see me in public, I don’t care that you are a fan, I don’t understand why people think I would. If you want to talk, why would you open with that? Tell me something technical that I don’t know. Then we are having a conversation.</p>

<hr />
<p><br /></p>

<p>We are in the middle of a revolution. Modern AI is the cherry on top, it’s just continuing the same trendline that had spreadsheets replace 4 bookkeepers with 1.</p>

<p>The industrial revolution required labor at mass scale, hence we got liberal democracy. But I think it’s over. If we don’t have a society where there’s a place for most people, governance will have to change.</p>

<p>Though don’t worry if you consider yourself one of those useless people, I do not think your life will become materially bad. Between the fact that it’s cheap to keep people alive, fed, and entertained, and that everyone no matter how secure believes they may be useless, it will be a lot more like retirement.</p>

<p>UBI is a <a href="https://www.piratewires.com/p/wireheading-city-george-hotz?f=home">double edged sword</a>. If you take it, you are no longer meaningfully a citizen.</p>

<hr />
<p><br /></p>

<p>It remains to be seen how this will all shape up, but the unprofitablity of the average person in rich countries cannot be ignored for too much longer. Their expectations exceed their market value, hence why protectionist economics to bring manufacturing back to America will not work.</p>

<p>Every society has its problems, but as I’ve been spending more time in China I think they are living in the future. Your average American has no idea how nice the cities are here. Walkable. I can’t get over how quiet the roads are, Chinese brand electric cars with big touch screens. High trust society.</p>

<p>I also learned that the ubiquitous mobile payments are not due to heavy handed government policy, but rather free market choice. And after you have used Alipay for a bit it really is convenient. Unlike credit cards, you can send money phone to phone by scanning a barcode, and I don’t think there’s a 3% fee sapping the economy.</p>

<p>Of course, a strong government is a devil’s bargain. When things are good they are really good, but when things go bad they can go really bad. However, things are good now, and it’s anyone’s guess how it plays out. If Yudkowskian AI safety is a real concern, you might need a strong government to have any hope.</p>

<hr />
<p><br /></p>

<p>Here’s a simple chart that shows where life will improve.</p>

<p><img src="/blog/assets/images/ai_trust.png" alt="image" /></p>

<p>These blog posts have become a bit of a travel diary. But these questions are way too big to ignore, and I think about them a lot. The optimism after the election was short lived, we are going to get bullshit protectionism and obstructionism.</p>

<p>Are we ready to strike a new deal restructuring Western society? I suspect not. The neoluddites still think they have a chance. But structurally they can’t ever succeed, they can just choose if they want to bring the West down with them or not.</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/11/29/nuke-acc
title: nuke/acc
url: https://geohot.github.io//blog/jekyll/update/2024/11/29/nuke-acc.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/11/29/nuke-acc.html
content_mime_type: text/html
content:
<p>I wrote a tweet about this but deleted it, since it’s a much more nuanced topic than can be discussed there. Nuclear weapons are the <a href="https://en.wikipedia.org/wiki/Chekhov%27s_gun">Chekhov’s gun</a> on the world stage.</p>

<p>When, if ever, are they going to be fired? When should they be?</p>

<hr />
<p><br /></p>

<p>I suspect this is not a question a lot of people give much thought to, since it’s obvious nukes are terrible and we should never use them, right? Mutually assured destruction and all that. But what if you think about this in a long term historical context? Surely in the past some terrible weapon was created and there was a great moral panic about it, probably something today that we consider quaint.</p>

<p>I suspect that in 100 years nuclear weapons will seem quaint. It’s so easy to imagine weapons that are way more horrible, think drone swarms and bioweapons. Oh that’s cute, it blows up a city. This new weapon seeks out and kills every &lt;insert race here&gt; person on earth and tortures them before they die. Even worse, these sort of weapons can be deployed tactically, where for nukes that’s actually kind of hard. Nobody wants an irradiated pile of rubble.</p>

<hr />
<p><br /></p>

<p>With that understood, when do we want to fire the nukes?</p>

<p>Firstly, they will not kill all humans. Probably around a third, on par with the black death or the <a href="https://en.wikipedia.org/wiki/Cambodian_genocide">Khmer Rouge</a>. And they will not create a nuclear winter ending all life. They may change the climate, but not more than the asteroid that killed the dinosaurs.</p>

<p>I understand the loss of short-term growth is a hard pill to swallow, but would we be better or worse off in 100 years if we fired all the nukes today? It is not clear to me that the answer is worse. The nukes will force systems to decentralize and become less complex, but in exchange those systems will become more robust. Will Google survive an all-out nuclear exchange? Will the Bitcoin blockchain?</p>

<hr />
<p><br /></p>

<blockquote>
  <p>“If you say why not bomb them tomorrow, I say why not today? If you say today at 5 o’clock, I say why not one o’clock?”</p>

  <p>– John von Neumann</p>
</blockquote>

<p>Do you really think the nukes won’t be used for the rest of human history? Assuming that history is long, I doubt it. Once the gun has been placed on the stage, it will be fired. Now or later? If you are an accelerationist, you want whatever is going to happen to happen sooner.</p>

<p>Welcome to nuke/acc</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/12/01/the-soul
title: The Soul
url: https://geohot.github.io//blog/jekyll/update/2024/12/01/the-soul.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/12/01/the-soul.html
content_mime_type: text/html
content:
<p>ugh the deep state didn’t come for me I just realized that what gets engagement is so <em>boring</em>. you wish there was a deep state that came for me. then at least there would be <em>some</em> adults in the room.</p>

<blockquote>
  <p>I used to fantasize about being or kissing Skrillex<br />
I need to delete Twitter ‘cause it gives me fucking mental illness<br />
Foaming at the mouth like I put a fucking Mento in it<br />
Get your ass off Twitter ‘cause it gives you fucking mental illness<br />
  – 8 now</p>
</blockquote>

<p>the <a href="https://open.spotify.com/album/3JBuWWY8OCHXMcQz5xxxCr?si=-AzkhTWNSjWf06vhtAigQw">whole album</a> is bangers btw. that’s my third quote from it. and now the blog post.</p>

<hr />
<p><br /></p>

<p>Western society is predicated around the existence of the individual, and what really is the individual without the soul, or <a href="https://en.wikipedia.org/wiki/Hard_problem_of_consciousness">consciousness</a> if you want the secular term. I used to believe in the individual, but I hadn’t really thought about it that much.</p>

<p>You are a machine learning algorithm. You have some priors in your DNA. You learn on data, RL style because your actions affect the next data you see; the dataset depends on the model.</p>

<p>There’s no room in this for an I. Control the DNA, control the data, control the outcome. Sad but true.</p>

<hr />
<p><br /></p>

<p>How much of this graph is people starting to figure this out? (US religious affiliation)</p>

<p><img src="/blog/assets/images/us_religion.png" width="400px" /></p>

<p>Can Christianity survive the death of the soul? Can liberalism survive the death of consciousness? How will it cope harder as progress in ML makes this belief more and more ridiculous? There will be everything on a continuous spectrum from logic gates to human level and beyond. Which models are individuals?</p>

<p>People used to believe the sun rose cause some dude pulled it in a chariot. People still believe they aren’t computers. Like the chariot people, they are just as wrong.</p>


guid: https://geohot.github.io//blog/jekyll/update/2024/12/07/elon-swing-voter
title: The Elon Swing Voter
url: https://geohot.github.io//blog/jekyll/update/2024/12/07/elon-swing-voter.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2024/12/07/elon-swing-voter.html
content_mime_type: text/html
content:
<p>I’m getting on a plane back to America tonight, been away for over 3 months. It sort of fills me with dread and anxiety. I remember going to the Apple store before I was leaving, the uhhhhhhh from the sales people was awful. 0 pride. Nobody cares. So different from the sales people at the Hong Kong Apple store. America has had its social fabric torn to shreds.</p>

<p>I’ll be back for a month, and I will see if it’s how I remember it, but I’m really not bullish. Wokism is really just Protestantism evolved, it’s not an aberration. I don’t think still fundamentally religious US society will fair very well with AI when it becomes clear just how unspecial people are.</p>

<p>Sidenote, I’m in 7th place on <a href="https://adventofcode.com/">Advent of Code</a> thanks to AI, and it is progressing so fast. A capability that was unknown to the world a few years ago. This is the only real issue that matters. It will change society more than you can possibly believe.</p>

<p>I’m predicting <a href="https://en.wikipedia.org/wiki/Religion_in_China">Chinese religion</a>, a “combination of Buddhism and Taoism with a Confucian worldview” will fair much better with AI. You can already see this in surveys of AI acceptance.</p>

<hr />
<p><br /></p>

<p>In 2016 it was clear Trump became a kingmaker for the Republican party. While he couldn’t guarantee an election win, he could hand victory to the Democrats if he went against whoever the Republicans nominated. All three Republican nominees since have been Trump.</p>

<p>Elon represents a similar force, but it’s easy to imagine him supporting the Democrats next election if things don’t go well this cycle. It’s possible Elon now actually has the complete power to choose the winner.</p>

<p>I know I’m an Elon swing voter. While there’s things I don’t agree with him on, it’s hard to imagine the clowns in the political establishment offering something remotely compelling against him. If the Democrats want a chance next election cycle, they pick someone like Mark Cuban and get Elon’s support. I predict they won’t. Anti-Elon will not be a tenable political position, and this is a good thing. Godspeed to <a href="https://x.com/LorenaSGonzalez/status/1259287879177531392">those who try</a>.</p>

<p>Even if I stay in the country, I’m leaving California. They need to turn around and get pro Musk people in government, or the <a href="https://en.wikipedia.org/wiki/California_exodus">mass exodus</a> will continue. Also looking into moving my companies out of Delaware. Dead end.</p>

<p>Now, within a everyone is pro Elon (pro-growth) political framework, there are still choices. Isolationism, tariffs, abortion, infrastructure spending, social safety net, etc… Once we are in that framework, politics can return, and there’s hope for America from a political standpoint. But if being anti-growth remains in the Overton window, there’s little hope. Does anyone think there’s hope for Europe?</p>

<hr />
<p><br /></p>

<p>Culturally, there’s a far deeper problem. <a href="/blog/jekyll/update/2024/12/01/the-soul.html">The soul</a> isn’t real, and this will be a very hard pill for many westerners to swallow. There’s already so little social fabric and this will only make it worse.</p>

<p>In rich Western society people’s expectations exceed their abilities. AI will pummel this even harder. All the clowns who worked jobs that were detrimental to society for fake money. The money is the map, not the territory! If you pervert a map you don’t change the territory, you are just lost.</p>

<p>We’ll see how it is being back, but I’m leaning towards leaving and applying for residency here. Btw, how does the US still tax nonresidents? Will be nice when the empire decays to the point it can no longer do that, the influence of the US on the payment rails of the world needs to go.</p>


guid: https://geohot.github.io//blog/jekyll/update/2025/01/22/death-of-the-visceral
title: Death of the Visceral
url: https://geohot.github.io//blog/jekyll/update/2025/01/22/death-of-the-visceral.html
feedurl: https://geohot.github.io/blog/feed.xml
base: https://geohot.github.io//blog/jekyll/update/2025/01/22/death-of-the-visceral.html
content_mime_type: text/html
content:
<blockquote>
  <p>Pulled up at a stop light<br />
Did drugs on the dashboard<br />
Look at the mess we made tonight<br />
  – Fer Sure (listen to it while reading this!)</p>
</blockquote>

<p>Imagine flying an x-wing down a corridor, having to turn the plane sideways to fit, a missile on your tail and closing, hitting the turbo, <em>feeling</em> the g force, coming up on the end of the corridor, pulling back <em>hard</em> on the stick the second the corridor opens, turning 90 degrees and watching the missile continue straight. Tingles. Adrenaline. Release.</p>

<p>Or if you don’t want sci-fi, imagine winter circa 1645 in America. Several of your group almost dead from lack of food, tracking a deer, spotting it, shooting it with your bow, hitting but the deer is trying to run, fast twitch muscles charging and leaping, plunging a knife into its heart and knowing at that moment everyone is going to be okay. Heart rate calming laying on the warm deer.</p>

<hr />
<p><br /></p>

<p>The modern world doesn’t have any <em>real</em> experiences like this any more. Survival has become a technocratic plod, making the right boring and careful decisions. There’s only <em>fake</em> experiences like the above, video games, sports, and drugs. And things like reckless driving, which are just kind of <em>stupid</em>.</p>

<p>As we march toward ASI, this will only get worse. What the unabomber describes as Type 2 experiences, ones where you can achieve results with serious effort, will vanish. All that will be left are things you can have for no effort (like food) and things you can never have (like world peace).</p>

<p>Even when humanity goes to Mars, we will be going as <em>cargo</em>.</p>

<hr />
<p><br /></p>

<p>I was told recently I’m not engaged in my life, and it’s pretty true. Until I see a solution to this problem, even a sketch of a solution, what’s the point? Why sprint if you aren’t sure where you are going?</p>

<p>I’m trying my best with comma and tiny corp, how do you make technology <em>itself</em> more accessible, not a fucking packaged product like when the default world talks about making technology more accessible. That’s just hiding complexity.</p>

<p>But it’s so hard. Companies don’t work like how I thought they did, they just…exist. Which I guess in retrospect is obvious, there’s no adults in the room. Knowing the future doesn’t help you change it. I am continually shocked at how little people understand about anything, they don’t even understand that they don’t understand.</p>

<hr />
<p><br /></p>

<p>Am I the same way? I try extremely hard to constantly test myself, if my predictions are wrong it’s clear I don’t understand. If I can’t build it I don’t understand. I’ll frequently read comments saying I don’t understand, but when I engage with these people they can’t explain what my world model gets wrong. A different meta world model? Or are they just idiots? To anyone who wants to supersede rationality, you better understand how to steelman every rationality argument.</p>

<p>If I want to succeed, I believe I have to change who I am, and I’m not sure if that’s possible. I believe I’ve been making efforts in that direction, but I haven’t seen results yet. Working on AI is both the only thing that matters and also so demoralizing because of the above.</p>

<p>I believe you have to give individuals control over the technology. And not by setting permissions in AWS that can be revoked, I mean in a nature sense. The ghost gunner is the real second amendment. This ideology holds me back so much in business, to the point I struggle to be competitive. But if you abandon that ideology, what’s the point to doing it at all?</p>

<p>I have to win with a hand tied behind my back. We make products designed for spiritual tops, not the majority of the world which is spiritual bottoms.</p>

<hr />
<p><br /></p>

<p>Now, perhaps I have an ace in the hole. With the rise of AI, the spiritual bottoms will soon have no cash, because AI is the ultimate spiritual bottom. It would take a highly skilled terrorist to build spiritual top AI and even I’m not that crazy. So we’ll only have bottom AI, and it will outcompete all the human bottoms. Advertising will vanish once the hypnodrones have been released. Those humans will likely wirehead themselves out of the picture.</p>

<p>This is the world I’m building for. Have you ever unconstrained your mind and thought about where the world is going? This won’t be like the steam engine replacing the horse, because all horses were bottoms. Ever seen a horse riding a human? Humanity bifurcates. Humans will retain control for the foreseeable future, the only question is, how many humans?</p>

<p>If it’s 10, I’m out. If it’s 10k, 50/50 I’m in. If it’s 10M, I’m definitely in. My goal is to make this number as large as possible, it’s my best chance of survival. Give control of the technology to as many people as possible in a deep <em>nature</em> sense, not a permissions sense.</p>

<p>In my opinion, this is what Elon gets wrong. Of course, he’s likely to be one of the 10, so maybe that’s why he doesn’t care. But what if he <em>isn’t</em>? Tesla and SpaceX are huge silos begging to be co-opted. I don’t think building silos like this is a good idea, compare the fate of the Telegram founder to the Signal founder.</p>

<p>Build technology and structures that are inseparable from the narrative you want, as opposed to ones you think you can wield for good. On a long enough timeline, it will always end up in your enemy’s hands. Imagine if the only thing they could do with it furthers your goals.</p>


guid: 66aafad22b234d0983de295a
title: ZFS RAIDZ2 - Achieving 157 GB/s
author: Neil Panchal
url: https://neil.computer/notes/zfs-raidz2/
feedurl: https://neil.computer/rss/
content_mime_type: text/html
content:
<hr><!--kg-card-begin: html--><p class="text-bold dark-red">Update: <a href="https://neil.computer/notes/zfs-raidz2/#note-5">See Note 5 below </a>. 157 GB/s is a misleading bandwidth due to the way fio lib handles the --filename option. Actual bandwidth is approximately 22 GB/s, which is still mighty impressive.</p><!--kg-card-end: html--><hr><p>I built a new server that&apos;s also going to serve as a NAS. It consists of 8 NVMe drives from Samsung (970 Evo 2TB) with a total capacity of 10.2 TB in RAIDZ2 configuration (2 drive redundancy). </p><h2 id="server-specs">Server specs:</h2><!--kg-card-begin: html--><table class="table">
<thead class="black bg-light-gray ba b--black">
<tr>
<th class="measure-12 measure-8-phone" colspan="2">Neil&apos;s Lab Server Specifications</th>
</tr>
</thead>
<tbody>
<tr>
<td>CPU Model</td>
<td>Intel&#xAE; Xeon&#xAE; Gold 6326, 16 Cores (32 Threads), 2.90 GHz (Base), 3.50 GHz (Turbo)</td>
</tr>
<tr>
<td>CPU Cooler</td>
<td>Noctua NH-U12S DX-4189</td>
</tr>
<tr>
<td>Motherboard</td>
<td>Supermicro X12SPi</td>
</tr>
<tr>
<td>RAM</td>
<td>Samsung 6x16GB (96 GB) DDR4-3200 RDIMM ECC PC4-25600R Dual Rank</td>
</tr>
<tr>
<td>NIC (On board)</td>
<td>Intel X550 2x 10G Base-T</td>
</tr>
<tr>
<td>NIC (PCIe)</td>
<td>Supermicro AOC-SGP-I4 4x 1GbE</td>
</tr>
<tr>
<td>OS NVMe</td>
<td>2x1TB(2TB) Samsung 970 Pro</td>
</tr>
<tr>
<td>OS NVMe Carrier</td>
<td>Supermicro AOC-SLG3-2M2 PCIe x8</td>
</tr>
<tr>
<td>NAS NVMe</td>
<td>8x2TB(16TB) Samsung 970 Evo</td>
</tr>
<tr>
<td>NAS NVMe Carrier</td>
<td>2x Quad Gigabyte GC-4XM2G4 PCIe x16</td>
</tr>
<tr>
<td>Power Supply</td>
<td>EVGA 750 Watt 210-GQ-0750-V1</td>
</tr>
<tr>
<td>Chassis</td>
<td>NZXT H510i Flow</td>
</tr>
</tbody>
</table><!--kg-card-end: html--><hr><h2 id="pcie-bifurcation">PCIe Bifurcation</h2><p>I am using 2x Gigabyte GC-4XM2G4 PCIe M.2 carrier cards, each can hold upto 4 NVMe drives. These cards have native <code>4x4x4x4</code> bifurcation mode in Supermicro BIOS. That means, they&apos;re presented to the OS as individual 4 lane PCIe devices, unlike HBA or RAID cards. All 32 PCIe lanes are directly hooked up to the CPU I/O, without having to go through South Bridge chipset.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2021/12/053117CA-300D-4CB9-88D2-14590762967E_1_102_a-1.jpeg" class="kg-image" alt="PCIe Bifurcation M.2 Carrier Cards" loading="lazy" width="1536" height="2048" srcset="https://neil.computer/content/images/size/w600/2021/12/053117CA-300D-4CB9-88D2-14590762967E_1_102_a-1.jpeg 600w, https://neil.computer/content/images/size/w1000/2021/12/053117CA-300D-4CB9-88D2-14590762967E_1_102_a-1.jpeg 1000w, https://neil.computer/content/images/2021/12/053117CA-300D-4CB9-88D2-14590762967E_1_102_a-1.jpeg 1536w" sizes="(min-width: 720px) 720px"><figcaption>PCIe Bifurcation M.2 Carrier Cards</figcaption></figure><hr><h2 id="build-a-zfs-raid-on-ubuntu-2004-server">Build a ZFS raid on Ubuntu 20.04 server:</h2><p>All NVMe drives are in PCIe Passthrough mode on VMWare ESXi:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2021/12/image-15.png" class="kg-image" alt="VMWare ESXi PCIe Passthrough Configuration" loading="lazy" width="1532" height="1494" srcset="https://neil.computer/content/images/size/w600/2021/12/image-15.png 600w, https://neil.computer/content/images/size/w1000/2021/12/image-15.png 1000w, https://neil.computer/content/images/2021/12/image-15.png 1532w" sizes="(min-width: 720px) 720px"><figcaption>VMWare ESXi PCIe Passthrough Configuration</figcaption></figure><hr><!--kg-card-begin: markdown--><p>Install ZFS utils:</p>
<pre><code>sudo apt install zfsutils-linux
</code></pre>
<p>Check if it is installed:</p>
<pre><code>neil@ubuntu:~$ lsmod | grep zfs
zfs                  4034560  6
zunicode              331776  1 zfs
zlua                  147456  1 zfs
zavl                   16384  1 zfs
icp                   303104  1 zfs
zcommon                90112  2 zfs,icp
znvpair                81920  2 zfs,zcommon
spl                   126976  5 zfs,icp,znvpair,zcommon,zavl
</code></pre>
<p>Check physical disks:</p>
<pre><code>neil@ubuntu:~$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0                       7:0    0 70.3M  1 loop /snap/lxd/21029
loop1                       7:1    0 55.4M  1 loop /snap/core18/2128
loop2                       7:2    0 32.3M  1 loop /snap/snapd/12704
sda                         8:0    0  100G  0 disk
&#x251C;&#x2500;sda1                      8:1    0    1M  0 part
&#x251C;&#x2500;sda2                      8:2    0    1G  0 part /boot
&#x2514;&#x2500;sda3                      8:3    0   99G  0 part
  &#x2514;&#x2500;ubuntu--vg-ubuntu--lv 253:0    0   99G  0 lvm  /
nvme0n1                   259:0    0  1.8T  0 disk
nvme5n1                   259:1    0  1.8T  0 disk
nvme4n1                   259:2    0  1.8T  0 disk
nvme2n1                   259:3    0  1.8T  0 disk
nvme1n1                   259:4    0  1.8T  0 disk
nvme6n1                   259:5    0  1.8T  0 disk
nvme3n1                   259:6    0  1.8T  0 disk
nvme7n1                   259:7    0  1.8T  0 disk
</code></pre>
<p>Optionally check for bad block sectors on the disk (I skipped this step since it takes a long time):</p>
<pre><code>sudo badblocks -b 512 -sw /dev/nvme7n1
Testing with pattern 0xaa: 3.68% done, 0:57 elapsed. (0/0/0 errors)
</code></pre>
<p>Locate disks by ID:</p>
<pre><code>neil@ubuntu:~$ ls -lh /dev/disk/by-id
lrwxrwxrwx 1 root root 10 Dec  6 04:45 dm-name-ubuntu--vg-ubuntu--lv -&gt; ../../dm-0
lrwxrwxrwx 1 root root 10 Dec  6 04:45 dm-uuid-LVM-Iw3mFxuF9uwlCMJ0yucrWHZwG82z1I6uX0tK6D7CT0Yfb4GXANWiCSjy3E4BoNos -&gt; ../../dm-0
lrwxrwxrwx 1 root root 10 Dec  6 04:45 lvm-pv-uuid-In8DDs-U2jd-TdgQ-BZM3-iACR-HPF3-PT61BX -&gt; ../../sda3
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.00253858119138c7 -&gt; ../../nvme1n1
lrwxrwxrwx 1 root root 13 Dec  6 05:12 nvme-eui.00253858119138ca -&gt; ../../nvme7n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.0025385811913a89 -&gt; ../../nvme5n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.002538581191b1f1 -&gt; ../../nvme3n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.002538581191b32b -&gt; ../../nvme4n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.002538581191c362 -&gt; ../../nvme6n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.002538581191c369 -&gt; ../../nvme0n1
lrwxrwxrwx 1 root root 13 Dec  6 04:45 nvme-eui.002538581191c472 -&gt; ../../nvme2n1

</code></pre>
<p>Create a file <code>/etc/zfs/vdev_id.conf</code> and add the following aliases:</p>
<pre><code>alias nvme0 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R849603J
alias nvme1 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R835621F
alias nvme2 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R849868J
alias nvme3 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R846665V
alias nvme4 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R846979M
alias nvme5 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R836071F
alias nvme6 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R849596Y
alias nvme7 /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S59CNM0R835624D
</code></pre>
<p>Run <code>sudo udevadm trigger</code> or simply reboot the machine. Aliases that we created will now show up under <code>/dev/disk/by-vdev</code>.</p>
<pre><code>neil@ubuntu:~$ ls -lh /dev/disk/by-vdev
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme0 -&gt; ../../nvme0n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme1 -&gt; ../../nvme1n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme2 -&gt; ../../nvme2n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme3 -&gt; ../../nvme3n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme4 -&gt; ../../nvme4n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme5 -&gt; ../../nvme5n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme6 -&gt; ../../nvme6n1
lrwxrwxrwx 1 root root 13 Dec  6 05:35 nvme7 -&gt; ../../nvme7n1
</code></pre>
<p>Create a <code>zpool</code>.</p>
<pre><code>neil@ubuntu:/dev/disk/by-vdev$ ls
nvme0  nvme1  nvme2  nvme3  nvme4  nvme5  nvme6  nvme7
neil@ubuntu:/dev/disk/by-vdev$ sudo zpool create tank raidz2 nvme0 nvme1 nvme2 nvme3 nvme4 nvme5 nvme6 nvme7
neil@ubuntu:/dev/disk/by-vdev$ zpool status
  pool: tank
 state: ONLINE
  scan: none requested
config:

	NAME        STATE     READ WRITE CKSUM
	tank        ONLINE       0     0     0
	  raidz2-0  ONLINE       0     0     0
	    nvme0   ONLINE       0     0     0
	    nvme1   ONLINE       0     0     0
	    nvme2   ONLINE       0     0     0
	    nvme3   ONLINE       0     0     0
	    nvme4   ONLINE       0     0     0
	    nvme5   ONLINE       0     0     0
	    nvme6   ONLINE       0     0     0
	    nvme7   ONLINE       0     0     0

errors: No known data errors
neil@ubuntu:/dev/disk/by-vdev$
</code></pre>
<p>For detailed status, run <code>zpool list -v</code>:</p>
<pre><code>neil@ubuntu:/dev/disk/by-id$ zpool list -v
NAME        SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
tank       14.5T   274K  14.5T        -         -     0%     0%  1.00x    ONLINE  -
  raidz2   14.5T   274K  14.5T        -         -     0%  0.00%      -  ONLINE
    nvme0      -      -      -        -         -      -      -      -  ONLINE
    nvme1      -      -      -        -         -      -      -      -  ONLINE
    nvme2      -      -      -        -         -      -      -      -  ONLINE
    nvme3      -      -      -        -         -      -      -      -  ONLINE
    nvme4      -      -      -        -         -      -      -      -  ONLINE
    nvme5      -      -      -        -         -      -      -      -  ONLINE
    nvme6      -      -      -        -         -      -      -      -  ONLINE
    nvme7      -      -      -        -         -      -      -      -  ONLINE

</code></pre>
<p>Great. Now we have a <code>zpool</code>.</p>
<!--kg-card-end: markdown--><hr><h2 id="create-a-zfs-filesystem">Create a ZFS filesystem:</h2><!--kg-card-begin: markdown--><p>Now that we have a <code>zpool</code> named <code>tank</code>, we can create a file system, enable <code>lz4</code> compression and mount it for performance testing:</p>
<pre><code>neil@ubuntu:/dev/disk/by-vdev$ sudo zfs create tank/fs
neil@ubuntu:/dev/disk/by-vdev$ zfs list
NAME      USED  AVAIL     REFER  MOUNTPOINT
tank      229K  10.5T     47.1K  /tank
tank/fs  47.1K  10.5T     47.1K  /tank/fs
neil@ubuntu:/dev/disk/by-vdev$ sudo zfs set compression=lz4 tank/fs
neil@ubuntu:/dev/disk/by-vdev$ sudo zfs set mountpoint=/home/neil/mnt/disk tank
</code></pre>
<!--kg-card-end: markdown--><p>Excellent. We should have a file system <code>fs</code> located at <code>~/mnt/disk/fs</code>. </p><hr><h2 id="performance-testing-using-fio">Performance testing using FIO:</h2><p>FIO testing suite is quite nifty for doing all sorts of I/O testing.</p><!--kg-card-begin: markdown--><p>Install FIO tools:</p>
<pre><code>sudo apt install fio
</code></pre>
<p>And run the benchmark with block size of <code>512k</code> and 28 workers:</p>
<pre><code>sudo fio --name=read_test \
        --filename=/home/neil/mnt/disk/dummy \
        --filesize=20G \
        --ioengine=libaio \
        --direct=1 \
        --sync=1 \
        --bs=512k \
        --iodepth=1 \
        --rw=read \
        --numjobs=28 \
        --group_reporting
</code></pre>
<!--kg-card-end: markdown--><p>157 GB/s is insane (sequential reads). That&apos;s with lz4 compression and RAIDZ2 configuration! It is trivial to start a sharing service such as <code>nfs</code> , <code>afp</code> or <code>smb</code> in Ubuntu. No need for FreeNAS or TrueNAS.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2021/12/image-14.png" class="kg-image" alt="FIO disk benchmark - 157 GB/s Sequential Reads" loading="lazy" width="2000" height="1199" srcset="https://neil.computer/content/images/size/w600/2021/12/image-14.png 600w, https://neil.computer/content/images/size/w1000/2021/12/image-14.png 1000w, https://neil.computer/content/images/size/w1600/2021/12/image-14.png 1600w, https://neil.computer/content/images/2021/12/image-14.png 2356w" sizes="(min-width: 720px) 720px"><figcaption>FIO disk benchmark - 157 GB/s Sequential Reads</figcaption></figure><p>I don&apos;t think we&apos;re close to saturating the PCIe bandwidth but using more vCPUs doesn&apos;t help with the bandwidth. So, it might be due to the limitations of NVMe controllers. </p><p>Hopefully, this is NAS is going to last a decade or so. ZFS is very portable and even if I lose VMWare ESXi image or something goes wrong with the system, I can pullout the PCIe cards housing the NVMe drives, insert them into another system and it will work.</p><p>By no means is this a comprehensive disk test. I fiddled around with many different knobs: <code>numjobs</code>, <code>blocksize</code>, <code>direct</code>, <code>sync</code>, etc. Most tests were around 70-100 GB/s sustained sequential reads. I suspect some of the speed is from caching in the RAM, which would explain the absurdity of 157 GB/s. Well, that&apos;s even more impressive that ZFS can do that! YMMV.</p><p>I&apos;d love to do a more comprehensive test but this thing needs to be permanently mounted and I need to transfer data over from the god-awful[1] QNAP NAS. It is making grumpy SATA noises.</p><hr><p>Thanks to <a href="https://yager.io/?ref=neil.computer">Will Yager</a> and Steve Ruff for help during this adventure!</p><p><strong>[1]</strong> Not because of the performance, but because of how bloated it really is. It literally takes 10 solid minutes to boot. With an attack surface so high (All kinds of apps, docker stuff, plugins, QNAP-cloud thingy, etc), it is completely ridiculous and I can&apos;t wait to get rid of it.</p><h2 id="note-1">Note 1</h2><p>I am not sure, I think some of it is cached in the RAM. I did a longer sustained test and I am getting about 70 GB/s with a 200GB file - this is definitely larger than 64GB RAM. Is it to do with lz4 compression? Fetching smaller blocks from disk and then decompressing it, thus inflating the bandwidth?</p><p>The initial file was created with fio rw=randwrite, so the dummy data is random. I verified with ext4 fs on a single NVMe drive and no matter what knobs I turn, I am getting around around 3.5 GB/s.</p><h2 id="note-2">Note 2</h2><p>I just did another 100GB file test with fio, full dump as follows getting about 80 GB/s. This test was run fresh after a system reboot and clearing the drive (no cache). How does this work?:</p><!--kg-card-begin: markdown--><pre><code>neil@ubuntu:~/mnt/disk/fs$ sudo fio --name=read_test         --filename=/home/neil/mnt/disk/fs/dummy         --filesize=100G         --ioengine=libaio         --direct=1         --sync=1         --bs=512k         --iodepth=1         --rw=read         --numjobs=28         --group_reporting
read_test: (g=0): rw=read, bs=(R) 512KiB-512KiB, (W) 512KiB-512KiB, (T) 512KiB-512KiB, ioengine=libaio, iodepth=1
...
fio-3.16
Starting 28 processes
read_test: Laying out IO file (1 file / 102400MiB)
Jobs: 28 (f=28): [R(28)][100.0%][r=78.0GiB/s][r=160k IOPS][eta 00m:00s]
read_test: (groupid=0, jobs=28): err= 0: pid=405516: Mon Dec 13 06:00:25 2021
  read: IOPS=152k, BW=74.4GiB/s (79.8GB/s)(2800GiB/37653msec)
    slat (usec): min=20, max=107934, avg=180.88, stdev=1535.31
    clat (nsec): min=248, max=9018.5k, avg=1114.70, stdev=9262.53
     lat (usec): min=20, max=107938, avg=182.57, stdev=1535.47
    clat percentiles (nsec):
     |  1.00th=[   334],  5.00th=[   422], 10.00th=[   494], 20.00th=[   620],
     | 30.00th=[   708], 40.00th=[   796], 50.00th=[   892], 60.00th=[   996],
     | 70.00th=[  1112], 80.00th=[  1272], 90.00th=[  1512], 95.00th=[  1768],
     | 99.00th=[  2800], 99.50th=[  8640], 99.90th=[ 32128], 99.95th=[ 47872],
     | 99.99th=[116224]
   bw (  MiB/s): min=46896, max=93840, per=99.96%, avg=76117.26, stdev=463.15, samples=2100
   iops        : min=93792, max=187680, avg=152233.31, stdev=926.29, samples=2100
  lat (nsec)   : 250=0.01%, 500=10.55%, 750=23.97%, 1000=25.87%
  lat (usec)   : 2=36.82%, 4=2.02%, 10=0.35%, 20=0.24%, 50=0.14%
  lat (usec)   : 100=0.03%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.01%
  cpu          : usr=1.59%, sys=54.53%, ctx=3119239, majf=0, minf=3916
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, &gt;=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     issued rwts: total=5734400,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=74.4GiB/s (79.8GB/s), 74.4GiB/s-74.4GiB/s (79.8GB/s-79.8GB/s), io=2800GiB (3006GB), run=37653-37653msec
neil@ubuntu:~/mnt/disk/fs$
</code></pre>
<!--kg-card-end: markdown--><h2 id="note-3">Note 3</h2><p>Running the entire VM with 2GB RAM reveals the story. It&apos;s due to RAM, but I still don&apos;t understand it. With 2GB RAM, we get ~ 20 GB/s which is close to combined bandwidth of all drives (RAIDZ2 would be 6x 3.5GB/s or close to ~20 GB/s). It still doesn&apos;t explain how we&apos;re able to reach absurd 80 GB/s on a long sustained test. </p><!--kg-card-begin: markdown--><pre><code>neil@ubuntu:~/mnt/disk/fs$ sudo fio --name=read_test         --filename=/home/neil/mnt/disk/fs/dummy         --filesize=100G         --ioengine=libaio         --direct=1         --sync=1         --bs=512k         --iodepth=1         --rw=read         --numjobs=28         --group_reporting
[sudo] password for neil:
read_test: (g=0): rw=read, bs=(R) 512KiB-512KiB, (W) 512KiB-512KiB, (T) 512KiB-512KiB, ioengine=libaio, iodepth=1
...
fio-3.16
Starting 28 processes
^Cbs: 28 (f=28): [R(28)][22.6%][r=17.5GiB/s][r=35.9k IOPS][eta 02m:55s]
fio: terminating on signal 2

read_test: (groupid=0, jobs=28): err= 0: pid=4712: Mon Dec 13 06:11:57 2021
  read: IOPS=41.2k, BW=20.1GiB/s (21.6GB/s)(1042GiB/51742msec)
    slat (usec): min=22, max=115406, avg=674.35, stdev=1331.96
    clat (nsec): min=296, max=7427.7k, avg=1850.79, stdev=14919.02
     lat (usec): min=23, max=115409, avg=677.17, stdev=1332.58
    clat percentiles (nsec):
     |  1.00th=[   548],  5.00th=[   676], 10.00th=[   772], 20.00th=[   916],
     | 30.00th=[  1032], 40.00th=[  1176], 50.00th=[  1320], 60.00th=[  1496],
     | 70.00th=[  1688], 80.00th=[  1944], 90.00th=[  2320], 95.00th=[  2672],
     | 99.00th=[  7584], 99.50th=[ 14656], 99.90th=[ 88576], 99.95th=[144384],
     | 99.99th=[301056]
   bw (  MiB/s): min=11908, max=59509, per=100.00%, avg=20627.88, stdev=256.00, samples=2884
   iops        : min=23815, max=119018, avg=41255.16, stdev=512.00, samples=2884
  lat (nsec)   : 500=0.49%, 750=8.39%, 1000=18.05%
  lat (usec)   : 2=55.11%, 4=16.39%, 10=0.82%, 20=0.35%, 50=0.21%
  lat (usec)   : 100=0.10%, 250=0.07%, 500=0.01%, 750=0.01%, 1000=0.01%
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.01%
  cpu          : usr=0.66%, sys=25.64%, ctx=4108148, majf=0, minf=3923
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, &gt;=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     issued rwts: total=2133831,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=20.1GiB/s (21.6GB/s), 20.1GiB/s-20.1GiB/s (21.6GB/s-21.6GB/s), io=1042GiB (1119GB), run=51742-51742msec
neil@ubuntu:~/mnt/disk/fs$
</code></pre>
<!--kg-card-end: markdown--><h2 id="note-4">Note 4</h2><p>Turning <code>lz4</code> compression didn&apos;t make much difference. </p><!--kg-card-begin: markdown--><pre><code>Last login: Mon Dec 13 06:09:18 2021 from 10.0.0.42
neil@ubuntu:~$ sudo zfs set compression=off tank/fs
[sudo] password for neil:
neil@ubuntu:~$ sudo fio --name=read_test         --filename=/home/neil/mnt/disk/fs/dummy         --filesize=100G         --ioengine=libaio         --direct=1         --sync=1         --bs=512k         --iodepth=1         --rw=read         --numjobs=28         --group_reporting
read_test: (g=0): rw=read, bs=(R) 512KiB-512KiB, (W) 512KiB-512KiB, (T) 512KiB-512KiB, ioengine=libaio, iodepth=1
...
fio-3.16
Starting 28 processes
Jobs: 28 (f=28): [R(28)][100.0%][r=78.4GiB/s][r=161k IOPS][eta 00m:00s]
read_test: (groupid=0, jobs=28): err= 0: pid=4520: Mon Dec 13 06:29:25 2021
  read: IOPS=156k, BW=76.2GiB/s (81.8GB/s)(2800GiB/36751msec)
    slat (usec): min=19, max=105788, avg=176.71, stdev=1535.16
    clat (nsec): min=247, max=16074k, avg=993.84, stdev=11978.23
     lat (usec): min=20, max=105793, avg=178.24, stdev=1535.33
    clat percentiles (nsec):
     |  1.00th=[   330],  5.00th=[   398], 10.00th=[   462], 20.00th=[   564],
     | 30.00th=[   644], 40.00th=[   716], 50.00th=[   788], 60.00th=[   884],
     | 70.00th=[   988], 80.00th=[  1128], 90.00th=[  1352], 95.00th=[  1576],
     | 99.00th=[  2256], 99.50th=[  4448], 99.90th=[ 27776], 99.95th=[ 47872],
     | 99.99th=[128512]
   bw (  MiB/s): min=20186, max=96350, per=100.00%, avg=78083.60, stdev=532.92, samples=2044
   iops        : min=40373, max=192700, avg=156166.03, stdev=1065.84, samples=2044
  lat (nsec)   : 250=0.01%, 500=13.73%, 750=31.22%, 1000=25.80%
  lat (usec)   : 2=27.66%, 4=1.06%, 10=0.22%, 20=0.16%, 50=0.09%
  lat (usec)   : 100=0.03%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
  lat (msec)   : 2=0.01%, 4=0.01%, 10=0.01%, 20=0.01%
  cpu          : usr=1.54%, sys=54.57%, ctx=2605775, majf=0, minf=3927
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, &gt;=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, &gt;=64=0.0%
     issued rwts: total=5734400,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=76.2GiB/s (81.8GB/s), 76.2GiB/s-76.2GiB/s (81.8GB/s-81.8GB/s), io=2800GiB (3006GB), run=36751-36751msec
neil@ubuntu:~$
</code></pre>
<!--kg-card-end: markdown--><hr><h2 id="note-5">Note 5</h2><p>I was able to get to the bottom of this madness. 157 GB/s (or even 70 GB/s) is a misleading number. Essentially, <code>fio</code> requires a separate file for each thread using the <code>:</code> symbol in the <code>--filename</code> argument.</p><p>I create separate files for each thread. Ran the test with 4, 8, and 16 jobs. Looks like it gets worse after 8 threads.</p><!--kg-card-begin: markdown--><pre><code>neil@ubuntu:~/mnt/disk$ ls
  dummy0  dummy10  dummy12  dummy14  dummy2  dummy4  dummy6  dummy8
  dummy1  dummy11  dummy13  dummy15  dummy3  dummy5  dummy7  dummy9
  neil@ubuntu:~/mnt/disk$ sudo fio --name=read_test \
  &gt;         --filename=/home/neil/mnt/disk/dummy0:/home/neil/mnt/disk/dummy1:/home/neil/mnt/disk/dummy2:/home/neil/mnt/disk/dummy3:/home/neil/mnt/disk/dummy4:/home/neil/mnt/disk/dummy5:/home/neil/mnt/disk/dummy6:/home/neil/mnt/disk/dummy7:/home/neil/mnt/disk/dummy8:/home/neil/mnt/disk/dummy9:/home/neil/mnt/disk/dummy10:/home/neil/mnt/disk/dummy11:/home/neil/mnt/disk/dummy12:/home/neil/mnt/disk/dummy13:/home/neil/mnt/disk/dummy14:/home/neil/mnt/disk/dummy15 \
  &gt;         --filesize=20G \
  &gt;         --ioengine=libaio \
  &gt;         --direct=1 \
  &gt;         --sync=1 \
  &gt;         --bs=512k \
  &gt;         --iodepth=1 \
  &gt;         --rw=read \
  &gt;         --numjobs=16 \
  &gt;         --group_reporting
</code></pre>
<!--kg-card-end: markdown--><p>This results in a modest ~ 15 GB/s sequential read speed. If I use <code>--numjobs=8</code>, I get around ~22 GB/s which is quite believable. Modest, but still mighty impressive! Thanks to folks on HN and Lobste.rs for chiming in.</p><hr><!--kg-card-begin: html--><a class="btn btn-sm bg-orange white hover-white hover-bg-black" href="https://news.ycombinator.com/item?id=29536627&amp;ref=neil.computer" title="Read Article - ZFS RAIDZ2 - Achieving 157 GB/s">Discuss on HN &#x2192;</a> <a class="btn btn-sm bg-dark-red white hover-white hover-bg-black" href="https://lobste.rs/s/z1pic6/zfs_raidz2_achieving_157_gb_s?ref=neil.computer" title="Read Article - ZFS RAIDZ2 - Achieving 157 GB/s">Discuss on Lobste.rs &#x2192;</a><!--kg-card-end: html-->


guid: 66aafad22b234d0983de295f
title: Teaching how to code is broken
author: Neil Panchal
url: https://neil.computer/notes/teaching-how-to-code-is-broken/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/01/Croneberg_and_Stokoe.png
content_mime_type: text/html
content:
<figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/Croneberg_and_Stokoe-1.png" class="kg-image" alt="Teaching how to code is broken" loading="lazy" width="1476" height="1008" srcset="https://neil.computer/content/images/size/w600/2022/01/Croneberg_and_Stokoe-1.png 600w, https://neil.computer/content/images/size/w1000/2022/01/Croneberg_and_Stokoe-1.png 1000w, https://neil.computer/content/images/2022/01/Croneberg_and_Stokoe-1.png 1476w" sizes="(min-width: 720px) 720px"></figure><img src="https://neil.computer/content/images/2022/01/Croneberg_and_Stokoe.png" alt="Teaching how to code is broken"><p>Typically:</p><ul><li>Chapter 1: Types</li><li>Chapter 2: Variables</li><li>Chapter 3: Operators/Math</li><li>Chapter 4: Control structures</li><li>Chapter 5: Arrays</li><li>Chapter 6: Functions</li><li>Chapter 7: Structs</li><li>Chapter 8: Classes and Objects</li><li>Chapter 9: Methods</li><li>Chapter 10: Inheritance and Polymorphism</li><li>Chapter 11: Some advanced thing X</li><li>Chapter 12: Some esoteric thing Y</li><li>Chapter 13: No one reaches the end so let&apos;s introduce concurrency here</li></ul><p>This is fine for a reference book for an experienced professional. It is a terrible format for tutorials or any guidance material that intends to teach people how to code, specifically beginners.</p><p>Why? Because none of these chapters answer the most important question a reader has, the entire time, WHY!? Why is all this important and what problems does it solve? When should I use this thing that I learned? Imagine if aliens landed on earth and we teach them everything about the shape of a fork, its material, how its made, typical ways of holding it, various shapes of forks, its history, and etymology, but never tell them that a fork is used to pick up food and stick it in the mouth.</p><p>Teaching how to code should be about problem-solving and effectively using the tools of a programming language to solve it. Say for example modeling a card game. Even better if the example is a continuous improvement starting from the very basics, hard coding stuff, and then increasing the scope as follows:</p><ul><li>Chapter 1: Cards (Constants, literals - hard code all cards)</li><li>Chapter 2: Suits (String concatenation, Int vs literal string)</li><li>Chapter 3: Ordered Ranks (Arrays, Variables to store each suit)</li><li>Chapter 4: Deck (Multidimensional arrays)</li><li>Chapter 5: Shuffling (Loops, Control flow, Member access, Assignment)</li><li>Chapter 6: Reusability of Shuffling algorithm (Functions, Pass by Value/Reference)</li><li>Chapter 7: Modeling a card game (I/O, Cards as Objects, Classes/Structs)</li><li>Chapter 8: Modeling a complex card game (Abstraction, Inheritance, Polymorphic behavior, Overriding methods, etc.)</li><li>Chapter 9: Multiplayer card game (Sockets and Networking, Server-Client communication, Concurrency)</li></ul><p>There are very few resources out there that truly embrace this type of teaching &#x2013; e.g. the absolutely brilliant <a href="https://natureofcode.com/?ref=neil.computer">Nature of Code</a> for beginners. Another one for experienced software engineers is <a href="https://www.oreilly.com/library/view/architecture-patterns-with/9781492052197/?ref=neil.computer">Architecture Patterns with Python</a> (models an e-commerce business from scratch).</p><p>I&apos;ve found that modeling or simulating something real like a card game is very effective. It teaches students about how to translate a real-world situation/problem/thing/phenomenon into code. Teaches them about assumptions and limitations of the model they&apos;ve built. Also, it teaches them about how to interrogate requirements imposed by the real world through simplification/abstraction or simply rejecting some aspects of it as &quot;Too complex, costly and impractical to model with no real benefit or a clear use case&quot; :-).</p><hr><p>Image credit: <a href="https://commons.wikimedia.org/wiki/File:Croneberg_and_Stokoe.png?ref=neil.computer">https://commons.wikimedia.org/wiki/File:Croneberg_and_Stokoe.png</a> Deafhistory101, CC BY-SA 4.0 <a href="https://creativecommons.org/licenses/by-sa/4.0?ref=neil.computer">https://creativecommons.org/licenses/by-sa/4.0</a>, via Wikimedia Commons</p>


guid: 66aafad22b234d0983de2960
title: Bell Labs Org Chart
author: Neil Panchal
url: https://neil.computer/notes/bell-labs-org-chart/
feedurl: https://neil.computer/rss/
content_mime_type: text/html
content:
<figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/001-2.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/001-2.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/001-2.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/001-2.jpg 1600w, https://neil.computer/content/images/2022/01/001-2.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><p></p><p>I&apos;ve always been curious about the story of Bell Labs &#x2013; how it was formed, why it was successful, its challenges and struggles, innovation engine, people, its organizational structure, operations, and its legacy. The <a href="https://web.archive.org/web/20220123055247/https://en.wikipedia.org/wiki/The_Idea_Factory">Idea Factory</a> by Jon Gertner is an excellent albeit slightly <a href="https://www.amazon.com/gp/customer-reviews/R10ZINB4B9O5I3?ref=neil.computer">inaccurate</a> summary of what, how, and why of Bell Labs. After finishing the book, I came across a curious listing on eBay. Without hesitation, I instantly purchased the <em>Bell Labs Pictorial Directory of the Design Engineering Center (Dept 375)</em> published on May 1, 1980. The cover design by itself is eye-catching with the good ol&apos; Ma Bell logo on the top-right corner.</p><p>This pictorial directory gives an abstract glimpse into the operations of Bell Labs&apos; &quot;Idea Factory&quot; simply through the titles of the departments and how they were organized. A few of these departments and teams are obsolete (e.g. Drafting group), nevertheless, there is much to learn/drool about.</p><p>I was curious &#x2013; how does Big Tech research compare to Bell Labs? I can&apos;t name a single thing from Google X or Amazon 126, Apple or Microsoft Research departments. Perhaps a faint idea of drones deliveries, balloon weather projects, AR/VR tech, failed chat apps, quantum something, and a lot of PR. Listing Bell Labs&apos; major inventions really put things into perspective: <strong>Laser, Solar-cells, Communications Satellites, Touch-tone telephones, Transistor, UNIX, C language, Digital Signal Processing (DSP), Cellular Telephones, Data Networking, Charge-coupled device (CCD), Information Theory, Television, Sound motion pictures, and a total of 8 Nobel Prizes in Physics</strong>.</p><p>Bell Labs was massive and operational for multiple decades, but it wouldn&apos;t hurt for the current Big Tech leadership to look back at the history and have a hard contemplation of what&apos;s going on with the current research. I think it would be difficult to replicate Bell Labs, if ever. Needless to say, I would kill to work at Bell Labs in the heydays, probably in the <em>Precision Graphics and Computer Applications Group </em>as I wear these shiny rose-tinted glasses. I want to work with all these super cool people of the bygone era.</p><p>Here is the entire Design Engineering Center org-chart. Mind you, this is just Dept 375. I don&apos;t know how many other departments existed at Bell Labs. It was just huge:</p><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/bell-labs-org-chart.png" class="kg-image" alt loading="lazy" width="1700" height="5200" srcset="https://neil.computer/content/images/size/w600/2022/01/bell-labs-org-chart.png 600w, https://neil.computer/content/images/size/w1000/2022/01/bell-labs-org-chart.png 1000w, https://neil.computer/content/images/size/w1600/2022/01/bell-labs-org-chart.png 1600w, https://neil.computer/content/images/2022/01/bell-labs-org-chart.png 1700w" sizes="(min-width: 720px) 720px"></figure><p>Original scans:</p><h2 id="bell-labs-pictorial-directory">Bell Labs Pictorial Directory</h2><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/002.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/002.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/002.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/002.jpg 1600w, https://neil.computer/content/images/2022/01/002.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/003.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/003.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/003.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/003.jpg 1600w, https://neil.computer/content/images/2022/01/003.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/004.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/004.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/004.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/004.jpg 1600w, https://neil.computer/content/images/2022/01/004.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/005.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/005.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/005.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/005.jpg 1600w, https://neil.computer/content/images/2022/01/005.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/006.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/006.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/006.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/006.jpg 1600w, https://neil.computer/content/images/2022/01/006.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/007.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/007.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/007.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/007.jpg 1600w, https://neil.computer/content/images/2022/01/007.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/008.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/008.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/008.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/008.jpg 1600w, https://neil.computer/content/images/2022/01/008.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/009.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/009.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/009.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/009.jpg 1600w, https://neil.computer/content/images/2022/01/009.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/010.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/010.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/010.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/010.jpg 1600w, https://neil.computer/content/images/2022/01/010.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/011.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/011.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/011.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/011.jpg 1600w, https://neil.computer/content/images/2022/01/011.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/012.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/012.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/012.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/012.jpg 1600w, https://neil.computer/content/images/2022/01/012.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/013.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/013.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/013.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/013.jpg 1600w, https://neil.computer/content/images/2022/01/013.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/014.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/014.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/014.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/014.jpg 1600w, https://neil.computer/content/images/2022/01/014.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/015.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/015.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/015.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/015.jpg 1600w, https://neil.computer/content/images/2022/01/015.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/017.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/017.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/017.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/017.jpg 1600w, https://neil.computer/content/images/2022/01/017.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/016.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/016.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/016.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/016.jpg 1600w, https://neil.computer/content/images/2022/01/016.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/018.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/018.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/018.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/018.jpg 1600w, https://neil.computer/content/images/2022/01/018.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/019.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/019.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/019.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/019.jpg 1600w, https://neil.computer/content/images/2022/01/019.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/020.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/020.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/020.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/020.jpg 1600w, https://neil.computer/content/images/2022/01/020.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/021.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/021.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/021.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/021.jpg 1600w, https://neil.computer/content/images/2022/01/021.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/022.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/022.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/022.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/022.jpg 1600w, https://neil.computer/content/images/2022/01/022.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/023.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/023.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/023.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/023.jpg 1600w, https://neil.computer/content/images/2022/01/023.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/024.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/024.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/024.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/024.jpg 1600w, https://neil.computer/content/images/2022/01/024.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/025.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/025.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/025.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/025.jpg 1600w, https://neil.computer/content/images/2022/01/025.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/026.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/026.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/026.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/026.jpg 1600w, https://neil.computer/content/images/2022/01/026.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/027.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/027.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/027.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/027.jpg 1600w, https://neil.computer/content/images/2022/01/027.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/028.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/028.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/028.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/028.jpg 1600w, https://neil.computer/content/images/2022/01/028.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/029.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/029.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/029.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/029.jpg 1600w, https://neil.computer/content/images/2022/01/029.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/030.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/030.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/030.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/030.jpg 1600w, https://neil.computer/content/images/2022/01/030.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/031.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/031.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/031.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/031.jpg 1600w, https://neil.computer/content/images/2022/01/031.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/032.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/032.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/032.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/032.jpg 1600w, https://neil.computer/content/images/2022/01/032.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/033.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/033.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/033.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/033.jpg 1600w, https://neil.computer/content/images/2022/01/033.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/034.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/034.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/034.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/034.jpg 1600w, https://neil.computer/content/images/2022/01/034.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/035.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/035.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/035.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/035.jpg 1600w, https://neil.computer/content/images/2022/01/035.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/036.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/036.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/036.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/036.jpg 1600w, https://neil.computer/content/images/2022/01/036.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/01/037.jpg" class="kg-image" alt loading="lazy" width="1700" height="2200" srcset="https://neil.computer/content/images/size/w600/2022/01/037.jpg 600w, https://neil.computer/content/images/size/w1000/2022/01/037.jpg 1000w, https://neil.computer/content/images/size/w1600/2022/01/037.jpg 1600w, https://neil.computer/content/images/2022/01/037.jpg 1700w" sizes="(min-width: 720px) 720px"></figure><p>Download as a <a href="https://neil.computer/content/files/bell-labs-directory.pdf">PDF</a>.</p><p>The end.</p><hr><p>Edit 1: Big Bang Theory was actually not discovered at Bell Labs, but its discovery was facililated by Bell Labs. Thank you to Ray Osborne for the correction.</p>


guid: 66aafad22b234d0983de2961
title: Berkeley Mono February Update
author: Neil Panchal
url: https://neil.computer/notes/berkeley-mono-february-update/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/02/oblique-font-production-1.png
content_mime_type: text/html
content:
<img src="https://neil.computer/content/images/2022/02/oblique-font-production-1.png" alt="Berkeley Mono February Update"><p>Hey Gang! First of all, thank you to everyone that participated in the Beta program. Feedback is very much appreciated.</p><p>Here is a quick update on the progress:</p><h2 id="websiteberkeleygraphicscom">Website - Berkeleygraphics.com</h2><p>It is already up: <a href="https://berkeleygraphics.com/?ref=neil.computer">https://berkeleygraphics.com</a> but does not have the Berkeley Mono pages yet.</p><!--kg-card-begin: markdown--><p>Stack is extremely simple:</p>
<ul>
<li>Python Flask</li>
<li>Docker</li>
<li>AWS S3</li>
<li>Completely server-side (No JS at all)</li>
<li>Payments through Stripe</li>
<li>Sentry (self-hosted) for alerts</li>
<li>AWS Cloudwatch for logs</li>
<li>Debian Bullseye 11 (self-hosted server)</li>
<li>Cloudflare + Cloudflare Analytics</li>
<li>No cookies</li>
</ul>
<!--kg-card-end: markdown--><p>I had fun designing this little download module (only visible after you purchase Berkeley Mono). It allows you to customize the font files for particular stylistic-set defaults. Basically, no need to change anything in your application, font files will be prebuilt for your liking:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/image-2.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1944" height="1172" srcset="https://neil.computer/content/images/size/w600/2022/02/image-2.png 600w, https://neil.computer/content/images/size/w1000/2022/02/image-2.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/image-2.png 1600w, https://neil.computer/content/images/2022/02/image-2.png 1944w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - Customer Account - Download Fonts</figcaption></figure><h2 id="berkeley-mono-specimens">Berkeley Mono Specimens</h2><p>This is the marketing bit. It&apos;s fun but also extremely time-consuming:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/Artboard-5.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1200" height="1696" srcset="https://neil.computer/content/images/size/w600/2022/02/Artboard-5.png 600w, https://neil.computer/content/images/size/w1000/2022/02/Artboard-5.png 1000w, https://neil.computer/content/images/2022/02/Artboard-5.png 1200w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Type Specimen</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/Artboard-1.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1200" height="1696" srcset="https://neil.computer/content/images/size/w600/2022/02/Artboard-1.png 600w, https://neil.computer/content/images/size/w1000/2022/02/Artboard-1.png 1000w, https://neil.computer/content/images/2022/02/Artboard-1.png 1200w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Type Specimen</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/Artboard-2.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1200" height="1696" srcset="https://neil.computer/content/images/size/w600/2022/02/Artboard-2.png 600w, https://neil.computer/content/images/size/w1000/2022/02/Artboard-2.png 1000w, https://neil.computer/content/images/2022/02/Artboard-2.png 1200w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Type Specimen</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/Artboard-3.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1200" height="1696" srcset="https://neil.computer/content/images/size/w600/2022/02/Artboard-3.png 600w, https://neil.computer/content/images/size/w1000/2022/02/Artboard-3.png 1000w, https://neil.computer/content/images/2022/02/Artboard-3.png 1200w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Type Specimen</figcaption></figure><h2 id="italics">Italics</h2><p>I am thrilled to announce, absolutely classic 16&#xBA; obliques. I think Oblique works better for code than true Italics. Also, in the context of Berkeley Mono, it is difficult to design flamboyant Italics while also being sufficiently legible, straightforward, and code-friendly. Personally, I am not a fan of <a href="https://www.typography.com/fonts/operator/overview?ref=neil.computer">Operator Mono</a> from Hoefler &amp; Co. although many people seem to like that sort of a thing. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/berkeley-mono-oblique.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="2000" height="1298" srcset="https://neil.computer/content/images/size/w600/2022/02/berkeley-mono-oblique.png 600w, https://neil.computer/content/images/size/w1000/2022/02/berkeley-mono-oblique.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/berkeley-mono-oblique.png 1600w, https://neil.computer/content/images/2022/02/berkeley-mono-oblique.png 2280w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Oblique</figcaption></figure><p>Designing proper obliques takes a long time because essentially it is designing a new typeface from scratch (almost). It is not a matter of slanting glyphs and calling it a day. Here is the most basic example. It gets quite involved for complicated glyphs such as <code>f</code> or <code>R</code>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/oblique-font-production.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1702" height="1196" srcset="https://neil.computer/content/images/size/w600/2022/02/oblique-font-production.png 600w, https://neil.computer/content/images/size/w1000/2022/02/oblique-font-production.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/oblique-font-production.png 1600w, https://neil.computer/content/images/2022/02/oblique-font-production.png 1702w" sizes="(min-width: 720px) 720px"><figcaption>Hand-tuning of Obliques</figcaption></figure><p>With a simple shear transformation, the corners get disproportionately heavy. This needs to be hand-tuned with a combination of shear + rotation (clockwise) + elbow grease.</p><p>Why 16 degrees? It is basically the classic oblique angle of Univers. Modern Univers from Linotype (now Monotype) uses a modest 12&#xBA; italic angle. I think that&apos;s too boring. Not 70&apos;s and 80&apos;s enough. More importantly, you want to easily distinguish between Roman and Italics. If they&apos;re too similar, it misses the point entirely.</p><h2 id="broad-language-support">Broad Language support</h2><p>Berkeley Mono will have full support for the following European languages:</p><!--kg-card-begin: markdown--><ul>
<li>Albanian</li>
<li>Croatian</li>
<li>Czech</li>
<li>Danish</li>
<li>Dutch</li>
<li>English</li>
<li>Estonian</li>
<li>Finnish</li>
<li>Georgian</li>
<li>German</li>
<li>Icelandic</li>
<li>Irish</li>
<li>Italian</li>
<li>Latvian</li>
<li>Lithuanian</li>
<li>Norwegian (Bokm&#xE5;l + Nynorsk)</li>
<li>Polish</li>
<li>Portuguese</li>
<li>Romanian</li>
<li>Romansh</li>
<li>Serbian</li>
<li>Slovak</li>
<li>Slovenian</li>
<li>Spanish</li>
<li>Swedish</li>
<li>Turkish</li>
<li>Welsh</li>
</ul>
<!--kg-card-end: markdown--><p>As well as Asian anglicization of:</p><!--kg-card-begin: markdown--><ul>
<li>Filipino</li>
<li>Indonesian</li>
</ul>
<!--kg-card-end: markdown--><p>Berkeley Mono complies with the following ISO 8859 standards:</p><!--kg-card-begin: markdown--><ul>
<li>ISO 8859-1 Latin-1 Western European</li>
<li>ISO 8859-2 Latin-2 Central European</li>
<li>ISO 8859-3 Latin-3 South European</li>
<li>ISO 8859-4 Latin-4 North European</li>
<li>ISO 8859-9 Latin-5 Turkish</li>
<li>ISO 8859-10 Latin-6 Nordic</li>
<li>ISO 8859-13 Latin-7 Baltic Rim</li>
<li>ISO 8859-15 Latin-9 Finnish, Estonian</li>
<li>ISO 8859-16 Latin-10 South-Eastern European</li>
</ul>
<!--kg-card-end: markdown--><h2 id="basic-latin-support">Basic Latin Support</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/berkeley-mono-basic-latin.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1708" height="840" srcset="https://neil.computer/content/images/size/w600/2022/02/berkeley-mono-basic-latin.png 600w, https://neil.computer/content/images/size/w1000/2022/02/berkeley-mono-basic-latin.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/berkeley-mono-basic-latin.png 1600w, https://neil.computer/content/images/2022/02/berkeley-mono-basic-latin.png 1708w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - Basic Latin Set</figcaption></figure><h2 id="western-european-support">Western European Support</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/berkeley-mono-western-european.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1740" height="1258" srcset="https://neil.computer/content/images/size/w600/2022/02/berkeley-mono-western-european.png 600w, https://neil.computer/content/images/size/w1000/2022/02/berkeley-mono-western-european.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/berkeley-mono-western-european.png 1600w, https://neil.computer/content/images/2022/02/berkeley-mono-western-european.png 1740w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - Western European Set</figcaption></figure><h2 id="central-european-set">Central European Set</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/berkeley-mono-central-european.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1740" height="1686" srcset="https://neil.computer/content/images/size/w600/2022/02/berkeley-mono-central-european.png 600w, https://neil.computer/content/images/size/w1000/2022/02/berkeley-mono-central-european.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/berkeley-mono-central-european.png 1600w, https://neil.computer/content/images/2022/02/berkeley-mono-central-european.png 1740w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - Central European Set</figcaption></figure><h2 id="south-eastern-european-set">South-Eastern European Set</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/berkeley-mono-south-eastern-european.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="1726" height="834" srcset="https://neil.computer/content/images/size/w600/2022/02/berkeley-mono-south-eastern-european.png 600w, https://neil.computer/content/images/size/w1000/2022/02/berkeley-mono-south-eastern-european.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/berkeley-mono-south-eastern-european.png 1600w, https://neil.computer/content/images/2022/02/berkeley-mono-south-eastern-european.png 1726w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - South-Eastern European Set</figcaption></figure><p>I am also planning for Greek language support but it seems to have stalled for now due to other activities:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/02/image-3.png" class="kg-image" alt="Berkeley Mono February Update" loading="lazy" width="2000" height="1334" srcset="https://neil.computer/content/images/size/w600/2022/02/image-3.png 600w, https://neil.computer/content/images/size/w1000/2022/02/image-3.png 1000w, https://neil.computer/content/images/size/w1600/2022/02/image-3.png 1600w, https://neil.computer/content/images/size/w2400/2022/02/image-3.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono - Greek Language Support</figcaption></figure><p>That&apos;s all for now. Stay tuned!</p><p>The end.</p>


guid: 66aafad22b234d0983de2964
title: Berkeley Mono Font Variant Popularity
author: Neil Panchal
url: https://neil.computer/notes/berkeley-mono-font-variant-popularity/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/03/Screen-Shot-2022-03-05-at-1.25.44-PM-1.png
content_mime_type: text/html
content:
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/03/twitter-card@2x.png" class="kg-image" alt="Berkeley Mono Font Variant Popularity" loading="lazy" width="1224" height="612" srcset="https://neil.computer/content/images/size/w600/2022/03/twitter-card@2x.png 600w, https://neil.computer/content/images/size/w1000/2022/03/twitter-card@2x.png 1000w, https://neil.computer/content/images/2022/03/twitter-card@2x.png 1224w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Typeface</figcaption></figure><img src="https://neil.computer/content/images/2022/03/Screen-Shot-2022-03-05-at-1.25.44-PM-1.png" alt="Berkeley Mono Font Variant Popularity"><p></p><p>Absolutely thrilled by the response after <a href="https://news.ycombinator.com/item?id=30557557&amp;ref=neil.computer">Hacker News launch of Berkeley Mono</a> Typeface. I am truly humbled by the feedback, interest and people that have keen interest in typography.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/03/image-3.png" class="kg-image" alt="Berkeley Mono Font Variant Popularity" loading="lazy" width="1332" height="1188" srcset="https://neil.computer/content/images/size/w600/2022/03/image-3.png 600w, https://neil.computer/content/images/size/w1000/2022/03/image-3.png 1000w, https://neil.computer/content/images/2022/03/image-3.png 1332w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Mono Font Variants</figcaption></figure><p></p><p>Quick update on people asking what&apos;s the most popular variant. Seems like Zero (Dot) and Seven (Regular) are winning! I personally use the most popular combination.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/03/image.png" class="kg-image" alt="Berkeley Mono Font Variant Popularity" loading="lazy" width="1182" height="998" srcset="https://neil.computer/content/images/size/w600/2022/03/image.png 600w, https://neil.computer/content/images/size/w1000/2022/03/image.png 1000w, https://neil.computer/content/images/2022/03/image.png 1182w" sizes="(min-width: 720px) 720px"><figcaption>Grafana Statistics for Berkeley Mono Font Variants</figcaption></figure><p>Check out <a href="https://berkeleygraphics.com/typefaces/berkeley-mono?ref=neil.computer">Berkeley Mono Typeface</a> if you haven&apos;t, it is now publicly available.</p>


guid: 66aafad22b234d0983de2967
title: Dear JetBrains. Don't mess with your UI.
author: Neil Panchal
url: https://neil.computer/notes/dear-jetbrains-dont-mess-with-your-ui/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/06/image-1.png
content_mime_type: text/html
content:
<img src="https://neil.computer/content/images/2022/06/image-1.png" alt="Dear JetBrains. Don&apos;t mess with your UI."><p>So we have yet a new UI overhaul. This time, bringing consumer-grade UI practices to the world of professionals.</p><p>Announcement:<br><a href="https://blog.jetbrains.com/idea/2022/05/take-part-in-the-new-ui-preview-for-your-jetbrains-ide/?ref=neil.computer">https://blog.jetbrains.com/idea/2022/05/take-part-in-the-new-ui-preview-for-your-jetbrains-ide/</a></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/06/image.png" class="kg-image" alt="Dear JetBrains. Don&apos;t mess with your UI." loading="lazy" width="1994" height="1592" srcset="https://neil.computer/content/images/size/w600/2022/06/image.png 600w, https://neil.computer/content/images/size/w1000/2022/06/image.png 1000w, https://neil.computer/content/images/size/w1600/2022/06/image.png 1600w, https://neil.computer/content/images/2022/06/image.png 1994w" sizes="(min-width: 720px) 720px"><figcaption>New Jet Brains interface</figcaption></figure><p>We&apos;re professionals. We can handle the complexity and the density of the current UI. You made a contract with us about what the UI would be like for a foreseeable future. A user interface is like an API for your eyeballs. Your vision system expects things in a certain place. The way we revise APIs, we ought to do the same with UIs. The cost of changing <em>anything</em> even if it is objectively better through whatever A/B testing you&apos;ve done, has to also account for the breakage of the contract it has made over years of daily usage. The bar needs to be <em>really</em> high.</p><p>So, what have we got here? Oh, the usual. Honest to god, I was playing bingo the moment I saw the headline on <a href="https://lobste.rs/s/nvqhk9/jetbrains_editors_are_getting_redesign?ref=neil.computer">Lobsters</a>. It is going to be something along these lines:</p><!--kg-card-begin: markdown--><ul>
<li><strong>More negative space.</strong> I&apos;ve yet to see any modern UI changes that go in the opposite direction. Literally, everything just got fatter. More padding and margin across the board.</li>
<li><strong>Removal of color from icons.</strong> Yup, iconography and the designers that used to work on them are long <a href="http://famfamfam.com/?ref=neil.computer">extinct</a>. Everything is open source so no one has the time and effort to work on icons anymore. We continue to use terrible simplistic icons everywhere. They&apos;re always made in a hurry using line segments to create a rough outline of the icon. I don&apos;t blame the designers one bit, it is just the situation. Designing icons is a <a href="https://www.smithsonianmag.com/innovation/how-susan-kare-designed-user-friendly-icons-for-first-macintosh-180973286/?ref=neil.computer">full time job</a>.</li>
<li><strong>Rounding of corners.</strong> Religion at this point.</li>
<li><strong>Homogenization.</strong> JetBrains wants to be like VSCode. Being different is not cool anymore. If we look at interface design across the board between 2010 and today, everything has become homogenized. The largest, and most powerful companies inject their <a href="https://material.io/?ref=neil.computer">consumer-grade ad-tech taste</a> into everything and anything.</li>
<li><strong>Animations.</strong> Haven&apos;t seen them but it will be filled with animations. The whole interface is going to feel like turbulent molasses. Mark my words.</li>
</ul>
<!--kg-card-end: markdown--><p>A double whammy. Not only are they breaking the UI, but they&apos;re also doing it for all the wrong reasons. A bit of spanking is needed in this space.</p><p>Goddamn it, I love PyCharm. What now? vim + billion plugins?</p>


guid: 66aafad22b234d0983de2968
title: Dear Spotify. Can we just get a table of songs?
author: Neil Panchal
url: https://neil.computer/notes/dear-spotify-can-we-just-get-table-of-songs/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/06/Screen-Shot-2022-06-04-at-12.52.08-AM.png
content_mime_type: text/html
content:
<img src="https://neil.computer/content/images/2022/06/Screen-Shot-2022-06-04-at-12.52.08-AM.png" alt="Dear Spotify. Can we just get a table of songs?"><p>Dear Spotify. I tried to search for podcasts on your Desktop app. I know you&apos;re into fancy cross-platform Electron framework. I&apos;ve come to terms with it. It&apos;s fine. It&apos;ll do. But, your understanding of interface design seems like it needs a bit of a history lesson. Back in iTunes Good Ol&apos; Days&#x2122; edition, we&apos;d get our search results in a list like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/06/image-2.png" class="kg-image" alt="Dear Spotify. Can we just get a table of songs?" loading="lazy" width="500" height="367"><figcaption>iTunes Good Ol&apos; Days&#x2122; Edition</figcaption></figure><p>Stick something in the search bar. Get results in a list. Life is good. Clear, concise, dense, and most importantly: FUNCTIONAL. It works.</p><p>But, when I try to do nothing more than search in your shiny app, I get this: </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/06/image-3.png" class="kg-image" alt="Dear Spotify. Can we just get a table of songs?" loading="lazy" width="2000" height="1246" srcset="https://neil.computer/content/images/size/w600/2022/06/image-3.png 600w, https://neil.computer/content/images/size/w1000/2022/06/image-3.png 1000w, https://neil.computer/content/images/size/w1600/2022/06/image-3.png 1600w, https://neil.computer/content/images/size/w2400/2022/06/image-3.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Spotify UI/UX search</figcaption></figure><p>Hmm. What the fuck is this!? Why are you trying to be edgy? Ok fine, I&apos;ll scroll down to the bottom and click &quot;Episodes&quot;. Looking for some Gene Kranz podcasts.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/06/image-4.png" class="kg-image" alt="Dear Spotify. Can we just get a table of songs?" loading="lazy" width="2000" height="1246" srcset="https://neil.computer/content/images/size/w600/2022/06/image-4.png 600w, https://neil.computer/content/images/size/w1000/2022/06/image-4.png 1000w, https://neil.computer/content/images/size/w1600/2022/06/image-4.png 1600w, https://neil.computer/content/images/size/w2400/2022/06/image-4.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Spotify UX/UI Episodes</figcaption></figure><p>Album grid. A giant wall of Podcast cover art. If there is a piece of information about a podcast that is the least useful, that would be the cover art. If there is a piece of information that is the most useful, that would be the title of the podcast as well as the name of Podcaster; both of those things appear to be either cut off or not visible. There is no other way to go through 18 pages of podcast search results. No list view. No compact view. This is all you get. I don&apos;t do memes on my blog, but if I were, it&apos;d be full of them. That&apos;s the feeling right now.</p><p>There are <em>so many</em> terrible UX/UI patterns everywhere in these tech companies. Apple, Google, Spotify, Netflix, Microsoft, Amazon, etc; I wish someone would pay me a yearly salary to just write about them. I would. I want to go yell in these companies. Hire me and hand me the entire UX/UI department. It would be called the &quot;Department of Functional Interfaces&quot;. </p><p>And, I&apos;m not even mad. Just desensitized by your assault, Spotify. Your buddy, Apple Music, sucks too.</p><p></p><p>Foobar2000? Where are you? Do you still have that tattoo on your arm that screams &quot;FUNCTIONALISM&quot;?</p>


guid: 66aafad22b234d0983de296b
title: Neofetch – Server Administration System
author: Neil Panchal
url: https://neil.computer/notes/neofetch/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/10/neofetch-1.png
content_mime_type: text/html
content:
<img src="https://neil.computer/content/images/2022/10/neofetch-1.png" alt="Neofetch &#x2013; Server Administration System"><p>I ssh into a lot of machines. Dozens of times a day. I need a quick way to see the health of the system as soon as I log in and with zero friction. I am obliged to use the one and only tool: <a href="https://github.com/dylanaraps/neofetch?ref=neil.computer"><code>neofetch</code></a>. Neofetch is a pillar of <a href="https://reddit.com/r/unixporn/?ref=neil.computer">r/unixporn</a>. It is the Altair of aesthetics, the expression of unix swaggery, the very manifestation of what it means to be a unix fan. It is a perfect tool for my ultimate nix flex: the Berkeley Graphics &#x2013; Server Administration System (SAS). </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://neil.computer/content/images/2022/10/neofetch.png" class="kg-image" alt="Neofetch &#x2013; Server Administration System" loading="lazy" width="2000" height="1419" srcset="https://neil.computer/content/images/size/w600/2022/10/neofetch.png 600w, https://neil.computer/content/images/size/w1000/2022/10/neofetch.png 1000w, https://neil.computer/content/images/size/w1600/2022/10/neofetch.png 1600w, https://neil.computer/content/images/size/w2400/2022/10/neofetch.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Berkeley Graphics - Server Administration System</figcaption></figure><p>As you can see, we have critical system information presented to the terminal user at a glance. Fitted with a fine typeface and a bright industrial-grade color scheme, the SAS offers a bespoke experience of ssh-ing into a machine. Of particular importance is the Memory and Disk usage, greatly enhanced by the bar graph representation for immediate visual capture.</p><p>If you&apos;d like to build emulate Berkeley Graphics SAS, please find the attached <a href="https://neil.computer/content/files/neofetch.conf">neofetch configuration file</a> for your perusal. This goes into the <code>~/.config/neofetch/config.conf</code> location. For a complete visualization extravaganza, <a href="https://berkeleygraphics.com/typefaces/berkeley-mono?ref=neil.computer">Berkeley Mono Typeface</a> can be purchased from our storefront. While it is of <a href="https://en.wikipedia.org/wiki/Ornament_and_Crime?ref=neil.computer">decorative</a> nature, it does function as a great way to see what&apos;s going on the remote server. The only downside is that <code>neofetch</code> is a little slow and approximately adds 220ms.</p><p>Sometimes, it is fine to take a break; decorate your world, systemize your frequent interactions and organize your tools. It is a sign of ardent craftsmanship, we all do it and that&apos;s good. I hope I can leave you with some inspiration. </p><p>PS &#x2013; SAS is a bit of tongue-in-cheek, next I need to write an article about my fascination for hyperformalization on this Thought Organization and Publication System (TOPS), aka my blog.</p>


guid: 66aafad22b234d0983de296c
title: How to install PostgreSQL in a custom directory
author: Neil Panchal
url: https://neil.computer/notes/how-to-install-postgresql-in-a-custom-directory/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2022/10/elephants.png
content_mime_type: text/html
content:
<figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2022/10/image.png" class="kg-image" alt="How to install PostgreSQL in a custom directory" loading="lazy" width="1000" height="600" srcset="https://neil.computer/content/images/size/w600/2022/10/image.png 600w, https://neil.computer/content/images/2022/10/image.png 1000w" sizes="(min-width: 720px) 720px"></figure><img src="https://neil.computer/content/images/2022/10/elephants.png" alt="How to install PostgreSQL in a custom directory"><p>When you install <code>postgresql</code> using <code>apt-get</code>, it runs <code>initdb</code> and automatically creates a <code>main</code> cluster. Typically, the default data directory location is in <code>/var/lib/postgresql/&lt;version&gt;/&lt;cluster&gt;/</code>.</p><p>There are three ways to install PostgreSQL in a custom directory. Options 1 and 2 are not ideal.</p><!--kg-card-begin: markdown--><ol>
<li>
<p>Install as default in <code>/var/lib/postgresql/&lt;version&gt;/&lt;cluster&gt;</code> and then move it somewhere else. Update location of the data directory in <code>/etc/postgresql/&lt;version&gt;/&lt;cluster&gt;/postgresql.conf</code>. This is not ideal because PostgreSQL ensures that the data directory is only accessible by <code>postgres</code> linux user when a cluster is created. You can misconfigure permissions by moving the data directory yourself.</p>
</li>
<li>
<p>Run <code>initdb</code> again, however, that&apos;s not quite possible unless you manually wipe out directories. <code>initdb</code> command will complain that there is already a cluster <code>main</code> located in <code>/var/lib/postgresql/&lt;version&gt;/&lt;cluster&gt;</code>.</p>
</li>
</ol>
<!--kg-card-end: markdown--><h2 id="proper-way">Proper way</h2><p>The proper way to go about this is to prevent PostgreSQL from running <code>initdb</code> until you&apos;re ready to create a cluster.</p><!--kg-card-begin: markdown--><ol>
<li>On a fresh system (without PostgreSQL), install <code>postgresql-common</code> package first. Do not install <code>postgresql</code> yet.</li>
</ol>
<pre><code class="language-bash">sudo apt install postgresql-common
</code></pre>
<ol start="2">
<li>Edit the <code>/etc/postgresql-common/createcluster.conf</code> and configure a custom data directory as follows:</li>
</ol>
<pre><code class="language-conf"># Default values for pg_createcluster(8)
# Occurrences of &apos;%v&apos; are replaced by the major version number,
# and &apos;%c&apos; by the cluster name. Use &apos;%%&apos; for a literal &apos;%&apos;.

# Create a &quot;main&quot; cluster when a new postgresql-x.y server package is installed
create_main_cluster = true

# Default start.conf value, must be one of &quot;auto&quot;, &quot;manual&quot;, and &quot;disabled&quot;.
# See pg_createcluster(8) for more documentation.
#start_conf = &apos;auto&apos;

# Default data directory.
data_directory = &apos;/my/awesome/location/postgresql/%v/%c&apos;
</code></pre>
<ol start="3">
<li>Install PostgreSQL:</li>
</ol>
<pre><code class="language-bash">sudo apt install postgresql
</code></pre>
<p>You should be all set. New database files will be created at <code>/my/awesome/localtion/</code>.</p>
<p>Unrelated but make sure to create a password for <code>postgres</code> superuser as follows:</p>
<pre><code class="language-bash">sudo -u postgres psql postgres

psql (14.5 (Debian 14.5-1.pgdg110+1))
Type &quot;help&quot; for help.

postgres=# \password
Enter new password for user &quot;postgres&quot;:
</code></pre>
<!--kg-card-end: markdown--><p>The end.</p><p>Image source: <a href="https://www.wwf.org.uk/learn/wildlife/african-elephants?ref=neil.computer">https://www.wwf.org.uk/learn/wildlife/african-elephants</a></p>


guid: 66aafad22b234d0983de296e
title: Favorite Perfumes
author: Neil Panchal
url: https://neil.computer/notes/favorite-perfumes/
feedurl: https://neil.computer/rss/
content_mime_type: text/html
content:
<p>A quick condensed list based on over 15 years of exploration in the world of perfumery. I didn&apos;t include obvious classics such as Polo Green and Aramis. If I were to pick 3 perfumes to wear for life, it would be: Hermes Bel Ami, Chanel Antaeus and Serge Lutens Chergui. Absolutely insane what&apos;s possible with perfumery.</p><p>I&apos;ll add more as I discover them. For now:</p>
<!--kg-card-begin: html-->
<table class="table"><thead class="black bg-light-gray ba b--black"><tr><th>House</th><th>Perfume</th><th>Type/Category</th><th>Year</th></tr></thead><tbody><tr><td>Caron</td><td>Yatagan</td><td>Woody Chypre</td><td>1976</td></tr><tr><td>Cartier</td><td>Pasha de Cartier &#xC9;dition Noire</td><td>Woody Aromatic</td><td>2013</td></tr><tr><td>Cartier</td><td>Santos de Cartier</td><td>Oriental Woody</td><td>1981</td></tr><tr><td>Chanel</td><td>Antaeus</td><td>Woody Chypre</td><td>1981</td></tr><tr><td>Chanel</td><td>Coromandel</td><td>Oriental</td><td>2007</td></tr><tr><td>Fr&#xE9;d&#xE9;ric Malle</td><td>Musc Ravageur</td><td>Oriental Spicy</td><td>2000</td></tr><tr><td>Guerlain</td><td>Jicky</td><td>Foug&#xE8;re Aromatic</td><td>1889</td></tr><tr><td>Guerlain</td><td>Vetiver</td><td>Woody Earthy</td><td>1961</td></tr><tr><td>Guerlain</td><td>Habit Rouge</td><td>Oriental Woody</td><td>1965</td></tr><tr><td>Guerlain</td><td>Heritage</td><td>Oriental Woody</td><td>1992</td></tr><tr><td>Guerlain</td><td>Shalimar</td><td>Oriental</td><td>1925</td></tr><tr><td>Hermes</td><td>Equipage</td><td>Woody Chypre</td><td>1970</td></tr><tr><td>Hermes</td><td>Equipage Geranium</td><td>Chypre Floral</td><td>2015</td></tr><tr><td>Hermes</td><td>Rocabar</td><td>Woody Spicy</td><td>1998</td></tr><tr><td>Hermes</td><td>Bel Ami</td><td>Leather</td><td>1986</td></tr><tr><td>Hermes</td><td>Bel Ami Vetiver</td><td>Woody Chypre</td><td>2013</td></tr><tr><td>Knize</td><td>Knize Ten</td><td>Leather</td><td>1924</td></tr><tr><td>Serge Lutens</td><td>Muscs Koublai Khan</td><td>Oriental Musky</td><td>1998</td></tr><tr><td>Serge Lutens</td><td>Chergui</td><td>Oriental Woody</td><td>2005</td></tr><tr><td>Serge Lutens</td><td>Santal Majuscule</td><td>Oriental Woody</td><td>2012</td></tr><tr><td>Serge Lutens</td><td>Fumerie Turque</td><td>Oriental</td><td>2003</td></tr><tr><td>Serge Lutens</td><td>Fille En Aiguilles</td><td>Oriental Spicy</td><td>2009</td></tr><tr><td>Serge Lutens</td><td>Daim Blond</td><td>Leather</td><td>2004</td></tr><tr><td>Tom Ford</td><td>Tobacco Oud</td><td>Oriental Woody</td><td>2013</td></tr><tr><td>Tom Ford</td><td>Tuscan Leather</td><td>Leather</td><td>2007</td></tr><tr><td>Truefitt &amp; Hill</td><td>Grafton</td><td>Woody Spicy</td><td>1983</td></tr></tbody></table>

<!--kg-card-end: html-->


guid: 66aafad22b234d0983de296f
title: Eternal Robustness
author: Neil Panchal
url: https://neil.computer/notes/eternal-robustness/
feedurl: https://neil.computer/rss/
enclosure_url: https://neil.computer/content/images/2023/09/CleanShot-2023-09-10-at-14.23.30@2x.png
content_mime_type: text/html
content:
<figure class="kg-card kg-image-card"><img src="https://neil.computer/content/images/2023/09/CleanShot-2023-09-10-at-14.23.30@2x-1.png" class="kg-image" alt="Eternal Robustness" loading="lazy" width="1228" height="720" srcset="https://neil.computer/content/images/size/w600/2023/09/CleanShot-2023-09-10-at-14.23.30@2x-1.png 600w, https://neil.computer/content/images/size/w1000/2023/09/CleanShot-2023-09-10-at-14.23.30@2x-1.png 1000w, https://neil.computer/content/images/2023/09/CleanShot-2023-09-10-at-14.23.30@2x-1.png 1228w" sizes="(min-width: 720px) 720px"></figure><img src="https://neil.computer/content/images/2023/09/CleanShot-2023-09-10-at-14.23.30@2x.png" alt="Eternal Robustness"><p>Delaware Law requires that any company establish in the State of Delaware (LLC, S-Corp or C-Corp) must have a Registered Agent physically located in Delaware. For a yearly charge, hiring such a Registered Agent is straightforward. They provide a physical mailing address, officially represent as a company agent, and forward any official notices.</p><p>While searching for such a service, I came across this gem:</p><blockquote>We guarantee your annual Registered Agent Fee will remain fixed at $50 per company, per year, for the life of your company. All you need to do is pay on time each year. For discounted pricing, you have the option of paying for two years in advance for $90 or three years in advance for $125. Our Registered Agent Fee has remained unchanged since 1981.</blockquote><p>This soothes the soul.</p><p>There is something so peaceful about permanency and eternal robustness, combined with a historical track record. This marketing copy signifies: &quot;Look, you can <em>trust</em> us. We can be depended upon. We are serious about our products and we will serve you with excellence year after year. Your involvement with us will be predictable and stable.&quot;</p><p>I wish more software and design people would embrace this philosophy. This is an undervalued value proposition.</p>


