<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://blog.hollandgibson.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.hollandgibson.com/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-14T03:07:57+00:00</updated><id>https://blog.hollandgibson.com/feed.xml</id><title type="html">Holland’s Blog</title><subtitle>The intersection of leadership, software engineering, and life.</subtitle><entry><title type="html">Consider targeting wasm32v1-none</title><link href="https://blog.hollandgibson.com/2026/04/13/targeting-wasm32v1.html" rel="alternate" type="text/html" title="Consider targeting wasm32v1-none" /><published>2026-04-13T00:00:00+00:00</published><updated>2026-04-13T00:00:00+00:00</updated><id>https://blog.hollandgibson.com/2026/04/13/targeting-wasm32v1</id><content type="html" xml:base="https://blog.hollandgibson.com/2026/04/13/targeting-wasm32v1.html"><![CDATA[<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#you_are_targeting_the_wrong_kind_of_wasm">You are targeting the wrong kind of wasm</a></li>
<li><a href="#the_problem">The problem</a>
<ul class="sectlevel2">
<li><a href="#small_note_wasm_for_the_web_vs_others">Small note: wasm for the web vs others</a></li>
</ul>
</li>
<li><a href="#shooting_yourself_in_the_foot">Shooting yourself in the foot</a>
<ul class="sectlevel2">
<li><a href="#the_big_things_missing">The big things missing</a></li>
<li><a href="#cant_you_just_not_use_those_calls">Can&#8217;t you just&#8230;&#8203; not use those calls?</a></li>
<li><a href="#example">Example</a></li>
</ul>
</li>
<li><a href="#solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#option_1_use_wasm32v1_none">Option 1: Use wasm32v1-none</a>
<ul class="sectlevel3">
<li><a href="#how_to_exclude_std">How to exclude <code>std</code></a></li>
<li><a href="#additional_benefits">Additional benefits</a></li>
<li><a href="#pitfalls">Pitfalls</a></li>
</ul>
</li>
<li><a href="#option_2_better_testing">Option 2: Better testing</a>
<ul class="sectlevel3">
<li><a href="#running_wasm_bindgen_test">Running wasm-bindgen-test</a></li>
<li><a href="#additional_benefits_2">Additional benefits</a></li>
<li><a href="#pitfalls_2">Pitfalls</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
</div>
<div class="sect1">
<h2 id="you_are_targeting_the_wrong_kind_of_wasm">You are targeting the wrong kind of wasm</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When building WebAssembly (wasm) projects, especially with rust, most advice is to build to <code>wasm32-unknown-unknown</code>.
This is generally bad advice.
With relatively simple changes you can use the compiler to your advantage rather than letting it lie to you.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
This is part 2 of my rust-wasm journey, see <a href="https://blog.hollandgibson.com/2026/04/02/rust-wasm">part 1 here</a>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the_problem">The problem</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The issue is that running something like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash">cargo build <span class="nt">--release</span> <span class="nt">--target</span> wasm32-unknown-unknown</code></pre>
</div>
</div>
<div class="paragraph">
<p>&#8230; ends up having the compiler shift many kinds of error to runtime instead of compile time.</p>
</div>
<div class="paragraph">
<p>One of the biggest benefits to using a language like rust is that you can make illegal states <em>unrepresentable</em>.<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>
This allows you to have the compiler stop you from making errors quickly and early in the design process.
So when you want to use rust to build a wasm library for the web, you shouldn&#8217;t have to give up on all the benefits of "compiler-driven-development".</p>
</div>
<div class="paragraph">
<p>This is compounded by the fact that testing dynamic libraries (wasm is by definition a dynamic library) is not straightforward at all.
So you may be fairly deep into coding or design and not realize you are trying to use something that will almost <em>never</em> work on the web.</p>
</div>
<div class="paragraph">
<p>You will be better served by instead targeting <code>wasm32v1-none</code> for the web.
More on how to do that later.</p>
</div>
<div class="sect2">
<h3 id="small_note_wasm_for_the_web_vs_others">Small note: wasm for the web vs others</h3>
<div class="paragraph">
<p>Most wasm is built for the web, and that&#8217;s what this blog post is discussing.
If you are building a wasm library as a plugin, or something to run in a "web worker" type setup, then you are probably aren&#8217;t targeting the <code>wasm32-unknown-unknown</code> target anyway.
You are probably building for the <code>wasm32-wasip2</code> or similar target, and swapping to one of those targets gets you largely the same benefit of targeting <code>wasm32v1-none</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="shooting_yourself_in_the_foot">Shooting yourself in the foot</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The problem is that <code>wasm32-unknown-unknown</code> includes the <code>std</code> library, but most of the <code>std</code> library is unusable in a wasm context.
There&#8217;s no filesystem, no I/O, no threads, etc.
This is (sort of) the point: the wasm sandbox can&#8217;t get into any trouble so from a consumer perspective, they can download and run wasm code without having to worry about it installing a rootkit or malware or something.</p>
</div>
<div class="paragraph">
<p>A somewhat fair reason for this situation&#8217;s existence is because <code>wasm32-unknown-unknown</code> is meant to be easy, and does not <em>only</em> target the web.</p>
</div>
<div class="sect2">
<h3 id="the_big_things_missing">The big things missing</h3>
<div class="paragraph">
<p><code>std</code> in rust contains a fair amount of things that won&#8217;t work on the web.
These are:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>I/O:</p>
<div class="ulist">
<ul>
<li>
<p><code>std::fs</code> - there&#8217;s no filesystem</p>
</li>
<li>
<p><code>std::net</code> - network calls are not permitted</p>
</li>
</ul>
</div>
</li>
<li>
<p>Concurrency:</p>
<div class="ulist">
<ul>
<li>
<p><code>std::thread</code> (or any non-<code>std</code> equivalent like <code>tokio::task</code>) - mainstream wasm is only single-threaded for now <sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup></p>
</li>
<li>
<p><code>std::sync::Mutex</code> (they sort of work, but not correctly)</p>
</li>
</ul>
</div>
</li>
<li>
<p>Time</p>
<div class="ulist">
<ul>
<li>
<p><code>std::time::Instant</code> - there&#8217;s no clock available and besides, even timing in JavaScript (js) has all sorts of limitations</p>
</li>
<li>
<p><code>SystemTime</code> - you have to access time via js</p>
</li>
</ul>
</div>
</li>
<li>
<p>Operating system</p>
<div class="ulist">
<ul>
<li>
<p><code>std::env</code> - environment variables don&#8217;t exist in a wasm context</p>
</li>
<li>
<p><code>std::process</code> - there&#8217;s no shell (like <code>bash</code>) available</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>There are others but they are not easy to discover and the <code>wasm32-unknown-unknown</code> target gets active maintenance anyway, but these big gaps are unlikely to change anytime soon.</p>
</div>
</div>
<div class="sect2">
<h3 id="cant_you_just_not_use_those_calls">Can&#8217;t you just&#8230;&#8203; not use those calls?</h3>
<div class="paragraph">
<p>Just don&#8217;t write code using any of these prohibited actions, you might think.
For simple wasm libraries this is actually quite feasible.
But once you start pulling in libraries, it can become very difficult to tell if a transitive dependency is going to try to do a network call or something else that won&#8217;t work before you ship your code.</p>
</div>
</div>
<div class="sect2">
<h3 id="example">Example</h3>
<div class="paragraph">
<p>I have created a demonstration project that compiles but will absolutely not work on the web: <a href="https://codeberg.org/humble_proton/blog-demos/src/branch/main/targeting_wasm32v1_none/stub_example" class="bare">https://codeberg.org/humble_proton/blog-demos/src/branch/main/targeting_wasm32v1_none/stub_example</a></p>
</div>
<div class="paragraph">
<p>For clarity here is a snippet of the wasm code, which compiles (and even passes unit tests):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="rust"><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">time</span><span class="p">::{</span><span class="n">SystemTime</span><span class="p">,</span> <span class="n">UNIX_EPOCH</span><span class="p">};</span>
<span class="k">use</span> <span class="nn">wasm_bindgen</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="n">wasm_bindgen</span><span class="p">;</span>

<span class="nd">#[wasm_bindgen]</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">epoch_secs</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="nb">u64</span> <span class="p">{</span>
    <span class="nn">SystemTime</span><span class="p">::</span><span class="nf">now</span><span class="p">()</span>
        <span class="nf">.duration_since</span><span class="p">(</span><span class="n">UNIX_EPOCH</span><span class="p">)</span>
        <span class="nf">.expect</span><span class="p">(</span><span class="s">"Time went backwards!"</span><span class="p">)</span>
        <span class="nf">.as_secs</span><span class="p">()</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>After it is loaded into a webpage, if you try to call this function you end up with an error message like: "unreachable executed" in firefox.<sup class="footnote">[<a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote.">3</a>]</sup></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="javascript"><span class="o">&gt;&gt;</span> <span class="nx">wasm</span><span class="p">.</span><span class="nf">epoch_secs</span><span class="p">()</span>
<span class="nx">Uncaught</span> <span class="nx">RuntimeError</span><span class="p">:</span> <span class="nx">unreachable</span> <span class="nx">executed</span>
    <span class="nx">epoch_secs</span> <span class="nx">http</span><span class="p">:</span><span class="c1">//[::1]:8000/target/pkg/stub_example.js:11</span>
    <span class="o">&lt;</span><span class="nx">anonymous</span><span class="o">&gt;</span> <span class="k">debugger</span> <span class="nb">eval</span> <span class="nx">code</span><span class="p">:</span><span class="mi">1</span>
<span class="nx">stub_example_bg</span><span class="p">.</span><span class="nx">wasm</span><span class="p">:</span><span class="mi">38494</span><span class="p">:</span><span class="mi">1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This is not a fun way to be writing code!</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="option_1_use_wasm32v1_none">Option 1: Use wasm32v1-none</h3>
<div class="paragraph">
<p>There is a straightforward solution: compile for the <code>wasm32v1-none</code> target instead.
Unfortunately, straightforward does not mean simple - this is not a drop in fix if you already have a large project.
The good news is that <code>wasm32v1-none</code> (in rust at least) still uses <code>wasm32-unknown-unknown</code> in the LLVM backend, so all other tools, browsers, etc still work exactly the same.<sup class="footnote">[<a id="_footnoteref_4" class="footnote" href="#_footnotedef_4" title="View footnote.">4</a>]</sup></p>
</div>
<div class="paragraph">
<p>The main benefit is that <code>wasm32v1-none</code> does <em>not</em> include the <code>std</code> library.
It only includes <code>core</code> and <code>alloc</code>.
Furthermore it only encompasses the W3C WebAssembly Core 1.0 spec with one W3C proposal: Mutable Global variable import &amp; export.
This means that this target is highly compatible across browsers.
In short, if you can compile to this target, this wasm will run on the web!</p>
</div>
<div class="paragraph">
<p>As a bonus, you can still use any of the W3C proposals that LLVM supports like reference types, multi-value, fixed width SIMD, etc - these are just a short <code>Cargo.toml</code> config away.</p>
</div>
<div class="paragraph">
<p>Compiling the <a href="https://codeberg.org/humble_proton/blog-demos/src/branch/main/targeting_wasm32v1_none/stub_example">stub_example</a> from with <code>wasm32v1-none</code> correctly fails:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="console"><span class="gp">$</span><span class="w"> </span>cargo build <span class="nt">--release</span> <span class="nt">--target</span> wasm32v1-none
<span class="go">   Compiling wasm-bindgen-shared v0.2.114
   Compiling unicode-ident v1.0.24
   Compiling cfg-if v1.0.4
   Compiling once_cell v1.21.4
   Compiling wasm-bindgen v0.2.114
error[E0463]: can't find crate for `std`
</span><span class="gp">  --&gt;</span><span class="w"> </span>/Users/humble_proton/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wasm-bindgen-0.2.114/src/lib.rs:53:1
<span class="go">   |
</span><span class="gp">53 | extern crate std;</span><span class="w">
</span><span class="go">   | ^^^^^^^^^^^^^^^^^ can't find crate
   |
   = note: the `wasm32v1-none` target may not support the standard library</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Indeed it does not support <code>std</code>!</p>
</div>
<div class="sect3">
<h4 id="how_to_exclude_std">How to exclude <code>std</code></h4>
<div class="paragraph">
<p>If you are unfamiliar with <code>no_std</code> build in rust, you just need to do a few steps (that are mostly copy and paste):</p>
</div>
<div class="paragraph">
<p>First you should exclude the <code>std</code> feature of <code>wasm-bindgen</code> (and any other crates) in your Cargo.toml:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">dependencies</span><span class="k">]</span>
<span class="n">wasm-bindgen</span> <span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"0.2.114"</span><span class="p">,</span><span class="w"> </span><span class="n">default-features</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="p">}</span> <i class="conum" data-value="1"></i><b>(1)</b></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>This should match the version of <code>wasm-bindgen</code> installed on your workstation.</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Then you need to do just a bit of ceremony (this is less scary than it looks) to tell the compiler you want to use the alloc crate (which usually isn&#8217;t available in <code>#[no_std]</code> environments, but is here).
Then specify a heap allocator<sup class="footnote">[<a id="_footnoteref_5" class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup> and specify a panic handler.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="rust"><span class="nd">#![no_std]</span>

<span class="c1">// Link the allocator and import the heap types: Vec, Rc, String, etc.</span>
<span class="k">extern</span> <span class="k">crate</span> <span class="n">alloc</span><span class="p">;</span>

<span class="k">use</span> <span class="nn">alloc</span><span class="p">::</span><span class="n">format</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">alloc</span><span class="p">::</span><span class="nn">string</span><span class="p">::</span><span class="nb">String</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">wasm_bindgen</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="n">wasm_bindgen</span><span class="p">;</span>

<span class="c1">// You can use DLmalloc just like `std` does, but we can do better </span><i class="conum" data-value="1"></i><b>(1)</b>
<span class="c1">// https://github.com/SFBdragon/talc/blob/master/talc/README_WASM.md</span>
<span class="nd">#[cfg(all(not(target_feature</span> <span class="nd">=</span> <span class="s">"atomics"</span><span class="nd">),</span> <span class="nd">target_family</span> <span class="nd">=</span> <span class="s">"wasm"</span><span class="nd">))]</span>
<span class="nd">#[global_allocator]</span>
<span class="k">static</span> <span class="n">TALC</span><span class="p">:</span> <span class="nn">talc</span><span class="p">::</span><span class="nn">wasm</span><span class="p">::</span><span class="n">WasmDynamicTalc</span> <span class="o">=</span> <span class="nn">talc</span><span class="p">::</span><span class="nn">wasm</span><span class="p">::</span><span class="nf">new_wasm_dynamic_allocator</span><span class="p">();</span>

<span class="nd">#[cfg(target_family</span> <span class="nd">=</span> <span class="s">"wasm"</span><span class="nd">)]</span>
<span class="nd">#[panic_handler]</span>
<span class="c1">// A panic results in a trap on wasm anyway so we can cut out the panic handler</span>
<span class="c1">// with wasm-bindgen later. We'll keep the standard panic handler on non-wasm</span>
<span class="c1">// builds (like `cargo test`) </span><i class="conum" data-value="2"></i><b>(2)</b>
<span class="k">fn</span> <span class="nf">panic</span><span class="p">(</span><span class="n">_info</span><span class="p">:</span> <span class="o">&amp;</span><span class="nn">core</span><span class="p">::</span><span class="nn">panic</span><span class="p">::</span><span class="n">PanicInfo</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="o">!</span> <span class="p">{</span>
    <span class="nn">core</span><span class="p">::</span><span class="nn">arch</span><span class="p">::</span><span class="nn">wasm32</span><span class="p">::</span><span class="nf">unreachable</span><span class="p">()</span>
<span class="p">}</span>

<span class="nd">#[wasm_bindgen]</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">join_strings</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="o">&amp;</span><span class="nb">str</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">String</span> <span class="p">{</span>
    <span class="nd">format!</span><span class="p">(</span><span class="s">"{a}{b}"</span><span class="p">)</span>
<span class="p">}</span>

<span class="nd">#[cfg(test)]</span>
<span class="k">mod</span> <span class="n">tests</span> <span class="p">{</span>
    <span class="k">use</span> <span class="k">super</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
    <span class="k">use</span> <span class="k">crate</span><span class="p">::</span><span class="nn">alloc</span><span class="p">::</span><span class="nn">string</span><span class="p">::</span><span class="nb">ToString</span><span class="p">;</span>

    <span class="c1">// Tests run on native arch; the logic is target-agnostic since we only use</span>
    <span class="c1">// `alloc`</span>
    <span class="nd">#[test]</span>
    <span class="k">fn</span> <span class="nf">duplicate_string</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">let</span> <span class="n">input</span> <span class="o">=</span> <span class="s">"abc"</span><span class="p">;</span>
        <span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="nf">join_strings</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">input</span><span class="p">);</span>
        <span class="nd">assert_eq!</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s">"abcabc"</span><span class="nf">.to_string</span><span class="p">());</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>See: <a href="https://github.com/SFBdragon/talc/blob/master/talc/README_WASM.md">talc&#8217;s wasm readme</a></td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Copying directly from the rustc book: "[wasm32v1-none] is compiled with -Cpanic=abort by default. Using -Cpanic=unwind would require using the WebAssembly exception-handling proposal stabilized mid-2025, and if that’s desired then you most likely don’t want to use this target and instead want to use wasm32-unknown-unknown instead."</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="additional_benefits">Additional benefits</h4>
<div class="paragraph">
<p>By excluding <code>std</code> you end up with a few nice side-benefits.
For one, your WASM blobs are smaller and probably more effecient because you are doing fewer and less allocations and when you do allocate you are using a better allocator.
Another benefit is that <code>#[no_std]</code> crates tend to be smaller and "do less" than the bigger crates.
This leads us to the downsides though:</p>
</div>
</div>
<div class="sect3">
<h4 id="pitfalls">Pitfalls</h4>
<div class="paragraph">
<p>Unfortunately, this approach may not be feasible for some projects.
For crates to support <code>#[no_std]</code>, they usually have to be built with that in mind from the beginning and many if not most "batteries included" type crates assume you in a <code>std</code> library environment, making compiling them without <code>std</code> close to impossible.
It is much easier start a new WASM project with this approach than it is to migrate a WASM project to a <code>#[no_std]</code> style dynamic library.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="option_2_better_testing">Option 2: Better testing</h3>
<div class="paragraph">
<p>Improved testing is always an improvement to the overall system.
There&#8217;s no such thing as a test you get for free, and tests are an overhead on development - they require maintenance and they only help improve the system, not actually fix anything.
Of course catching bugs early is much more effective than catching them in production (or even worse, having a customer report it to you because you didn&#8217;t catch it).</p>
</div>
<div class="paragraph">
<p>Testing is only as good as your coverage<sup class="footnote">[<a id="_footnoteref_6" class="footnote" href="#_footnotedef_6" title="View footnote.">6</a>]</sup> and the logic/assumptions it validates.
The compiler can catch bugs as you write them, whereas tests only catch bugs after you&#8217;ve written them (unless you are a strict Test-Driven-Development developer).
However, we do have a way to test the existing WASM dynamic library <em>in situ</em>, with a wasm executor which is a huge improvement to the alternative of doing unit tests with your computer&#8217;s architecture (i.e. when you run <code>cargo test</code>).</p>
</div>
<div class="paragraph">
<p>The only real method for this option is the admittedly experimental <code>wasm-bindgen-test</code>.
<a href="https://wasm-bindgen.github.io/wasm-bindgen/wasm-bindgen-test/index.html">Their documentation on usage</a> is pretty good, so I&#8217;ll only briefly summarize what we do.</p>
</div>
<div class="sect3">
<h4 id="running_wasm_bindgen_test">Running wasm-bindgen-test</h4>
<div class="paragraph">
<p>A complete example can be found at <a href="https://codeberg.org/humble_proton/blog-demos/src/branch/main/targeting_wasm32v1_none/stub_example_with_tests">my codeberg blog-demos repo</a>.</p>
</div>
<div class="paragraph">
<p>First, add a "rlib" type of library build.
That is in your <code>Cargo.toml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">lib</span><span class="k">]</span>
<span class="n">crate-type</span> <span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"cdylib"</span><span class="p">,</span> <span class="s">"rlib"</span><span class="p">]</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This will allow you to run integration tests.</p>
</div>
<div class="paragraph">
<p>Secondly, add the wasm-bindgen-test crate to your project:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash">cargo add <span class="nt">--dev</span> wasm-bindgen-test</code></pre>
</div>
</div>
<div class="paragraph">
<p>Thirdly, write your integration tests in <code>tests/wasm.rs</code>.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="rust"><span class="k">use</span> <span class="nn">wasm_bindgen_test</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>

<span class="c1">// Run tests in a browser (remove this to run in Node.js/headless)</span>
<span class="nd">wasm_bindgen_test_configure!</span><span class="p">(</span><span class="n">run_in_browser</span><span class="p">);</span>

<span class="k">use</span> <span class="nn">stub_example</span><span class="p">::</span><span class="nn">time</span><span class="p">::</span><span class="n">measure_delay_ms</span><span class="p">;</span>

<span class="nd">#[wasm_bindgen_test]</span>
<span class="k">pub</span> <span class="k">fn</span> <span class="nf">check_delay_test</span><span class="p">()</span> <span class="p">{</span>
    <span class="cs"># measure_delay_ms() uses time which isn't available on wasm</span>
    <span class="nd">assert!</span><span class="p">(</span><span class="nf">measure_delay_ms</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Then you can run the tests:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash"><span class="c"># check for logic bugs first, running your other tests:</span>
cargo <span class="nb">test</span> <span class="nt">--release</span>
<span class="c"># check for wasm errors:</span>
wasm-pack <span class="nb">test</span> <span class="nt">--firefox</span> <span class="c"># or safari, or chrome</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Open a browser to <a href="http://127.0.0.1:8000" class="bare">http://127.0.0.1:8000</a> and you&#8217;ll see output like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="text">Loading Wasm module...

running 2 tests
test check_delay_test ... FAIL

failures:

---- check_delay_test output ----
    error output:
        panicked at /rustc/4a4ef493e3a1488c6e321570238084b38948f6db/library/std/src/sys/pal/wasm/../unsupported/time.rs:13:9:
        time not implemented on this platform

        Stack:

        __wbg_get_imports/__wbg_new_d6846beabaecc372/&lt;@http://127.0.0.1:8000/wasm-bindgen-test:375:25
        logError@http://127.0.0.1:8000/wasm-bindgen-test:705:18
        __wbg_new_d6846beabaecc372@http://127.0.0.1:8000/wasm-bindgen-test:374:57</code></pre>
</div>
</div>
<div class="paragraph">
<p>The important line is: <code>time not implemented on this platform</code></p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
You can also run in <code>--headless</code> mode which doesn&#8217;t require a manual step of refreshing the browser page, but headless mode doesn&#8217;t capture output when the code panicks (or at least I couldn&#8217;t figure out how to get it to work).
If there&#8217;s a logic bug that only exists in the wasm version, the output in headless mode is probably enough - you can always try headless mode first.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="additional_benefits_2">Additional benefits</h4>
<div class="paragraph">
<p>You can use all the crates you want, even if they have functions that would execute unsupported system calls.
As long as your code doesn&#8217;t launch those functions, you can run in the browser without problems!</p>
</div>
</div>
<div class="sect3">
<h4 id="pitfalls_2">Pitfalls</h4>
<div class="paragraph">
<p>Larger wasm bundles.</p>
</div>
<div class="paragraph">
<p>Safety is reliant on you writing good tests - which is not as great a strategy when compared to compiler-enforced checks.
We could accomplish largely the same thing in TypeScript or JavaScript and avoid this whole wasm mess!</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>By default, you should start rust wasm projects with <code>wasm32v1-none</code> instead of <code>wasm32-unknown-unknown</code> - this trims the size of your wasm bundle and gives you better safety guarantees.
If you are working with existing projects (especially ones with lots of imported crates) then I would recommend integrating wasm-pack testing into your workflow, this isn&#8217;t as seamless and integrated as targeting <code>wasm32v1-none</code> but you can still check that you aren&#8217;t calling non-existing functions if you get good test coverage.
If you know about other languages compiling to wasm like C or GoLang, you may want to consider <code>wasm32v1-none</code> for much of the same reasons.</p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. I am not the first person to think about this, I learned it from <a href="https://geeklaunch.io/blog/make-invalid-states-unrepresentable/" class="bare">https://geeklaunch.io/blog/make-invalid-states-unrepresentable/</a> and from <a href="https://www.youtube.com/@NoBoilerplate" class="bare">https://www.youtube.com/@NoBoilerplate</a>
</div>
<div class="footnote" id="_footnotedef_2">
<a href="#_footnoteref_2">2</a>. The Web Workers kind of thread management is available across all major browsers, but this has very different semantics than the standard rust threads, so you&#8217;d need to use a specialty library like <a href="https://github.com/RReverser/wasm-bindgen-rayon">wasm-bindgen-rayon</a> or do it manually with enabling of nightly features.
</div>
<div class="footnote" id="_footnotedef_3">
<a href="#_footnoteref_3">3</a>. Tested in Firefox 149.0 on MacOS, but this should be the same on all browsers.
</div>
<div class="footnote" id="_footnotedef_4">
<a href="#_footnoteref_4">4</a>. See the <a href="https://doc.rust-lang.org/rustc/platform-support/wasm32v1-none.html">rustc page on wasm32v1-none</a> for more information.
</div>
<div class="footnote" id="_footnotedef_5">
<a href="#_footnoteref_5">5</a>. I suggest using talc, which is designed for wasm in mind and outperforms the default allocator, DLmalloc. If you have to add one anyway, why not just use a better one?
</div>
<div class="footnote" id="_footnotedef_6">
<a href="#_footnoteref_6">6</a>. There&#8217;s a lot more to testing than seeking 100% "coverage", but going from very low coverage to "mostly covered" is pretty good - I personally shoot for 85%.
</div>
</div>]]></content><author><name>Holland Gibson</name></author><category term="2026" /><category term="software" /><category term="rust" /><category term="web" /><summary type="html"><![CDATA[The "default" wasm32-unknown-unknown target shouldn&#8217;t be your first choice.]]></summary></entry><entry><title type="html">DIY rust on the web</title><link href="https://blog.hollandgibson.com/2026/04/02/rust-wasm.html" rel="alternate" type="text/html" title="DIY rust on the web" /><published>2026-04-02T00:00:00+00:00</published><updated>2026-04-02T00:00:00+00:00</updated><id>https://blog.hollandgibson.com/2026/04/02/rust-wasm</id><content type="html" xml:base="https://blog.hollandgibson.com/2026/04/02/rust-wasm.html"><![CDATA[<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#rust_and_wasm">Rust and WASM</a></li>
<li><a href="#wasm_in_2026">WASM in 2026</a></li>
<li><a href="#getting_started">Getting started</a>
<ul class="sectlevel2">
<li><a href="#requirements">Requirements</a></li>
</ul>
</li>
<li><a href="#without_frameworks_how_does_rust_run_on_the_web">Without frameworks, how does rust run on the web?</a>
<ul class="sectlevel2">
<li><a href="#creating_a_bare_bones_project">Creating a bare bones project</a></li>
</ul>
</li>
<li><a href="#exploring_the_results">Exploring the results</a></li>
<li><a href="#improving_file_sizes">Improving file sizes</a>
<ul class="sectlevel2">
<li><a href="#step_0_gzip">Step 0 - gzip</a></li>
<li><a href="#step_1_compilation_options">Step 1 - compilation options</a></li>
<li><a href="#step_2_wasm_opt">Step 2 - wasm-opt</a></li>
<li><a href="#optimization_summary">Optimization summary</a></li>
</ul>
</li>
<li><a href="#references_and_continued_learning">References and Continued Learning</a></li>
<li><a href="#addendum">Addendum</a></li>
</ul>
</div>
<div class="sect1">
<h2 id="rust_and_wasm">Rust and WASM</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Rust as a low-level language makes it a great candidate for WASM compilation.
There&#8217;s no garbage collector to contend with, but there&#8217;s also many fewer footguns than, say, C++ (or so I hear).
Rust can easily compile to wasm32 targets, has strong typing, has a great DevX, and is high performance.
It is also just a lot nicer to work with than JavaScript (js), at least in my opinion.</p>
</div>
<div class="paragraph">
<p>The <a href="https://wasm-bindgen.github.io/wasm-bindgen/introduction.html">wasm-bindgen</a> book is fantastic (and I borrow many ideas from that book here), but it skips a couple steps and some explanation so this blog post can help go over starting a rust-wasm project from scratch.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="wasm_in_2026">WASM in 2026</h2>
<div class="sectionbody">
<div class="paragraph">
<p>WASM in (early) 2026 means a developer must accept the following:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>no direct DOM access from WASM</p>
</li>
<li>
<p>single-threaded only</p>
</li>
<li>
<p>high performance (low overhead) js-wasm function calls</p>
</li>
<li>
<p>lower performance js-wasm data passing (all objects get re-encoded)</p>
</li>
<li>
<p>32-bit architecture</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="getting_started">Getting started</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can follow along and see working examples at <a href="https://codeberg.org/humble_proton/blog-demos" class="bare">https://codeberg.org/humble_proton/blog-demos</a></p>
</div>
<div class="sect2">
<h3 id="requirements">Requirements</h3>
<div class="ulist">
<ul>
<li>
<p>rust and cargo toolchain installed (go to <a href="https://rustup.rs/">rustup.rs</a>)</p>
</li>
<li>
<p><code>wasm-bindgen-cli</code> installed: <code>cargo binstall wasm-bindgen-cli</code></p>
<div class="ulist">
<ul>
<li>
<p><code>binstall</code> and <code>install</code> are interchangeable but <code>binstall</code> is better if you have it installed<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
</li>
</ul>
</div>
</li>
<li>
<p><code>wasm32-unknown-unknown</code> target available. I.e. <code>rustup target add wasm32-unknown-unknown</code></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="without_frameworks_how_does_rust_run_on_the_web">Without frameworks, how does rust run on the web?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>There&#8217;s essentially only 1 absolutely required crate, but an additional 2 are very useful.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="https://crates.io/crates/wasm-bindgen">wasm-bindgen</a> - library and tools for generating bindings for the web</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Then there are 2 crates for importing APIs,</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><a href="https://crates.io/crates/web-sys">web-sys</a> - imports for all of the <a href="https://developer.mozilla.org/en-US/docs/Web/API">Web APIs</a>. Things like  File, Clipboard, HtmlElement, Window to name a few.</p>
</li>
<li>
<p><a href="https://crates.io/crates/js-sys">js-sys</a> - imports for all the JS APIs, like Promise, Array, BigInt, etc.</p>
</li>
</ol>
</div>
<div class="sect2">
<h3 id="creating_a_bare_bones_project">Creating a bare bones project</h3>
<div class="paragraph">
<p>This is the shortest amount of steps from empty directory to working web demo.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Create the project: <code>cargo init minimal_wasm_demo --lib</code></p>
</li>
<li>
<p>Change the project to a dynamic library (in the <code>Cargo.toml</code>):</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre>[lib]
crate-type = ["cdylib"]</pre>
</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>add the wasm bindgen crate: <code>cargo add wasm-bindgen</code></p>
</li>
<li>
<p>in the <code>src/lib.rs</code> file:</p>
<div class="olist loweralpha">
<ol class="loweralpha" type="a">
<li>
<p>add <code>use wasm_bindgen::prelude::wasm_bindgen;</code> to the top.</p>
</li>
<li>
<p>add <code>#[wasm_bindgen]</code> before the <code>pub fn add(left: u64, right: u64)</code> function that was created for you in step 1. This is what tells the <code>wasm-bindgen</code> CLI tool that the adder function should be accessible from JavaScript.</p>
</li>
</ol>
</div>
</li>
<li>
<p><code>cargo build --release --target wasm32-unknown-unknown</code></p>
</li>
<li>
<p><code>wasm-bindgen target/wasm32-unknown-unknown/release/minimal.wasm --out-dir target/pkg --typescript --target web</code> - This generates the bindings and "glue" code to/from js.</p>
</li>
</ol>
</div>
<div class="sect3">
<h4 id="success">Success!</h4>
<div class="dlist">
<dl>
<dt class="hdlist1">You now have 4 files in your <code>target/pkg</code> directory</dt>
<dd>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><code><em>_</em>.js</code> - javascript bindings.</p>
</li>
<li>
<p><code><em>_</em>.d.ts</code> - typescript header file for the wasm bindings.</p>
</li>
<li>
<p><code><em>_</em>.wasm</code> - the wasm file!</p>
</li>
<li>
<p><code><em>_</em>.wasm.d.ts</code> - the typescript header file for the wasm functions.</p>
</li>
</ol>
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="exploring_the_results">Exploring the results</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To avoid <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a> problems, you must use a simple web server.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash">python3 <span class="nt">-m</span> http.server</code></pre>
</div>
</div>
<div class="paragraph">
<p>or if you don&#8217;t have python3 installed:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash">cargo binstall miniserve
miniserve <span class="nb">.</span> <span class="nt">--index</span> <span class="s2">"index.html"</span> <span class="nt">-p</span> 8000</code></pre>
</div>
</div>
<div class="paragraph">
<p>The console window will show <code>1 + 2 = 3</code> if everything is working correctly.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="improving_file_sizes">Improving file sizes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The above example results in a 1.2KB wasm file and 3.8KB js file.
We can do things ranging from very easy to not-very-easy to optimize the artifacts.</p>
</div>
<div class="paragraph">
<p>File size is not the only metric that matters, but it <em>usually</em> is the most important.
Having a function execute a few more bytecode-level instructions is not humanly perceptible unless you are doing a ton of processing, so sacrificing a few milliseconds of execution time is better than sacrificing many milliseconds in just http transit time<sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup>.</p>
</div>
<div class="paragraph">
<p>Furthermore, some optimizations don&#8217;t even affect the performance of the wasm object at all, and <em>everyone</em> must download your wasm file to their browser to do anything with it.</p>
</div>
<div class="paragraph">
<p>Lastly, size optimizations are like any other kind of software optimization:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Judge via objective benchmarks (in this case, file size)</p>
</li>
<li>
<p>Let the compiler/profiler tell you where to optimize (check each optimization to make sure each successive optimization helps rather than hurts!)</p>
</li>
<li>
<p>Consider what you lose by optimizing (this is typically "readability", but in this case you probably aren&#8217;t reading the WAT<sup class="footnote">[<a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote.">3</a>]</sup> version of your wasm binary, so this shouldn&#8217;t matter as much)</p>
</li>
</ol>
</div>
<div class="sect2">
<h3 id="step_0_gzip">Step 0 - gzip</h3>
<div class="paragraph">
<p>Nearly every web server uses gzip to compress data before sending it to the client, so this should be essentially automatic. Check that your server does this and call it a day.</p>
</div>
<div class="paragraph">
<p>For example, we are now left with (roughly) an 844 byte wasm file.
That&#8217;s about a savings of 30% in this case.</p>
</div>
</div>
<div class="sect2">
<h3 id="step_1_compilation_options">Step 1 - compilation options</h3>
<div class="sect3">
<h4 id="link_time_optimization_lto">Link Time Optimization (LTO)</h4>
<div class="paragraph">
<p>At the expense of longer compilation times, we can compile with LTO enabled which improves memory layout and locality (among many other things:<sup class="footnote">[<a id="_footnoteref_4" class="footnote" href="#_footnotedef_4" title="View footnote.">4</a>]</sup></p>
</div>
<div class="paragraph">
<p>Add:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">profile</span><span class="k">.</span><span class="n">release</span><span class="k">]</span>
<span class="n">lto</span> <span class="o">=</span><span class="w"> </span><span class="kc">true</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>to the <code>Cargo.toml</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="optimize_for_size_over_speed">Optimize for size over speed</h4>
<div class="paragraph">
<p>We can also inform LLVM to compile rust with overall layout optimizations.
There are two main options for <a href="https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level">opt-level</a>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>"s": optimize for binary size</p>
</li>
<li>
<p>"z": optimize for binary size, but also turn off loop vectorization (i.e. more aggressive, performance impacts)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Loop vectorization can also <em>increase</em> file size in some cases, so remember point #2 of optimizations mentioned above, check each compiler option!</p>
</div>
<div class="paragraph">
<p>Add:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">profile</span><span class="k">.</span><span class="n">release</span><span class="k">]</span>
<span class="n">opt-level</span> <span class="o">=</span><span class="w"> </span><span class="s">"z"</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>to the <code>Cargo.toml</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="results">Results</h4>
<div class="paragraph">
<p>So we are left with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="toml"><span class="k">[</span><span class="n">profile</span><span class="k">.</span><span class="n">release</span><span class="k">]</span>
<span class="n">lto</span> <span class="o">=</span><span class="w"> </span><span class="kc">true</span>
<span class="n">opt-level</span> <span class="o">=</span><span class="w"> </span><span class="s">"z"</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>in the <code>Cargo.toml</code>.</p>
</div>
<div class="paragraph">
<p>This results in a 655 Byte wasm file (939 Bytes before gzip compression). For this very bare-bones project, there are no loops so there&#8217;s no difference between <code>s</code> and <code>z</code> optimization levels.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="step_2_wasm_opt">Step 2 - wasm-opt</h3>
<div class="sect3">
<h4 id="installation">Installation</h4>
<div class="paragraph">
<p>Another tool we can use is the <code>wasm-opt</code> tool, available from the "binaryen" project.
Download the appropriate release from <a href="https://github.com/WebAssembly/binaryen/releases">their latest GitHub releases</a> and expand it to a known place on your system (I put mine at <code>$HOME/Applications/binaryen</code>), then add the <code>bin</code> folder to your <code>$PATH</code> (if you are unsure what this means, see <a href="https://unix.stackexchange.com/a/26059">this StackOverflow answer</a>).</p>
</div>
<div class="paragraph">
<p>I&#8217;m using version 128 for the purposes of this post:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="console"><span class="gp">$</span><span class="w"> </span>wasm-opt <span class="nt">--version</span>
<span class="go">wasm-opt version 128 (version_128)</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="usage">Usage</h4>
<div class="paragraph">
<p><code>wasm-opt --help</code> explains everything, but a short synopsis is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="bash"><span class="c"># Optimize for size.</span>
wasm-opt <span class="nt">-Os</span> <span class="nt">-o</span> output.wasm input.wasm

<span class="c"># Optimize aggressively for size.</span>
wasm-opt <span class="nt">-Oz</span> <span class="nt">-o</span> output.wasm input.wasm

<span class="c"># Optimize for speed.</span>
wasm-opt <span class="nt">-O</span> <span class="nt">-o</span> output.wasm input.wasm

<span class="c"># Optimize aggressively for speed.</span>
wasm-opt <span class="nt">-O3</span> <span class="nt">-o</span> output.wasm input.wasm</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="results_2">Results</h4>
<div class="paragraph">
<p>This should be ran <em>after</em> wasm-pack.</p>
</div>
<div class="paragraph">
<p>We end up with a 611 Byte wasm file (800 Bytes before gzip compression).</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="optimization_summary">Optimization summary</h3>
<div class="paragraph">
<p>So, we can shave off a fair amount of code size with just running some basic commands.</p>
</div>
<div class="paragraph">
<p>We started with just a <code>--release</code> build and wasm-pack resulted in a 1.2KB wasm file.
After changing the compiler flags, and running <code>wasm-opt</code> we are left with an 800 Byte wasm file, that&#8217;s roughly 35% size for free!<sup class="footnote">[<a id="_footnoteref_5" class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup>
Gzip compression (added by the server automatically) compresses this even further.</p>
</div>
<div class="paragraph">
<p>Note that these optimizations were chosen because they didn&#8217;t require any changes to our code, no restrictions to rust features, etc.</p>
</div>
<div class="paragraph">
<p>There are more&#8230;&#8203; <em>advanced</em> optimizations we can perform, but that is outside the scope of this blog post.</p>
</div>
<div class="paragraph">
<p>If you want to look into them yourself, try:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>avoiding the use of an allocator (and using <code>#[no_std]</code>)</p>
</li>
<li>
<p>profiling your code: <a href="https://rustwasm.github.io/book/reference/code-size.html#size-profiling" class="bare">https://rustwasm.github.io/book/reference/code-size.html#size-profiling</a></p>
</li>
<li>
<p>consider using trait objects over generics</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="references_and_continued_learning">References and Continued Learning</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p><a href="https://wasm-bindgen.github.io/wasm-bindgen/introduction.html">wasm-bindgen book</a> (successor to the rustwasm project)</p>
</li>
<li>
<p><code>wasm-pack</code> is another useful CLI tool that can streamline a lot of the process used in this post. Install with: <code>cargo install wasm-pack</code> or <a href="https://drager.github.io/wasm-pack/installer/">follow their directions</a>.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="addendum">Addendum</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This is the WAT version of the result from step 2 of the optimizations looks like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="common_lisp"><span class="p">(</span><span class="nv">module</span>
 <span class="p">(</span><span class="k">type</span> <span class="nv">$0</span> <span class="p">(</span><span class="nv">func</span><span class="p">))</span>
 <span class="p">(</span><span class="k">type</span> <span class="nv">$1</span> <span class="p">(</span><span class="nv">func</span> <span class="p">(</span><span class="nv">param</span> <span class="nv">i64</span> <span class="nv">i64</span><span class="p">)</span> <span class="p">(</span><span class="nv">result</span> <span class="nv">i64</span><span class="p">)))</span>
 <span class="p">(</span><span class="nb">import</span> <span class="s">"./minimal_bg.js"</span> <span class="s">"__wbindgen_init_externref_table"</span> <span class="p">(</span><span class="nv">func</span> <span class="nv">$fimport$0</span><span class="p">))</span>
 <span class="p">(</span><span class="nv">memory</span> <span class="nv">$0</span> <span class="mi">17</span><span class="p">)</span>
 <span class="p">(</span><span class="nv">data</span> <span class="nv">$0</span> <span class="p">(</span><span class="nv">i32.const</span> <span class="mi">1048576</span><span class="p">)</span> <span class="s">"\c0\00/Users/humble_proton/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wasm-bindgen-0.2.114/src/externref.rs\00/rust/deps/dlmalloc-0.2.11/src/dlmalloc.rs\00RefCell already borrowedassertion failed: psize &gt;= size + min_overhead\00r\00\10\00*\00\00\00\b1\04\00\00\t\00\00\00assertion failed: psize &lt;= size + max_overhead\00\00r\00\10\00*\00\00\00\b7\04\00\00\r\00\00\00\02\00\10\00o\00\00\00\7f\00\00\00\11\00\00\00\02\00\10\00o\00\00\00\8c\00\00\00\11"</span><span class="p">)</span>
 <span class="p">(</span><span class="nv">data</span> <span class="nv">$1</span> <span class="p">(</span><span class="nv">i32.const</span> <span class="mi">1048916</span><span class="p">)</span> <span class="s">"\04"</span><span class="p">)</span>
 <span class="p">(</span><span class="nv">table</span> <span class="nv">$0</span> <span class="mi">1024</span> <span class="nv">externref</span><span class="p">)</span>
 <span class="p">(</span><span class="nb">export</span> <span class="s">"memory"</span> <span class="p">(</span><span class="nv">memory</span> <span class="nv">$0</span><span class="p">))</span>
 <span class="p">(</span><span class="nb">export</span> <span class="s">"add"</span> <span class="p">(</span><span class="nv">func</span> <span class="nv">$0</span><span class="p">))</span>
 <span class="p">(</span><span class="nb">export</span> <span class="s">"__wbindgen_externrefs"</span> <span class="p">(</span><span class="nv">table</span> <span class="nv">$0</span><span class="p">))</span>
 <span class="p">(</span><span class="nb">export</span> <span class="s">"__wbindgen_start"</span> <span class="p">(</span><span class="nv">func</span> <span class="nv">$fimport$0</span><span class="p">))</span>
 <span class="p">(</span><span class="nv">func</span> <span class="nv">$0</span> <span class="p">(</span><span class="nv">param</span> <span class="nv">$0</span> <span class="nv">i64</span><span class="p">)</span> <span class="p">(</span><span class="nv">param</span> <span class="nv">$1</span> <span class="nv">i64</span><span class="p">)</span> <span class="p">(</span><span class="nv">result</span> <span class="nv">i64</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">i64.add</span>
   <span class="p">(</span><span class="nv">local.get</span> <span class="nv">$0</span><span class="p">)</span>
   <span class="p">(</span><span class="nv">local.get</span> <span class="nv">$1</span><span class="p">)</span>
  <span class="p">)</span>
 <span class="p">)</span>
 <span class="c1">;; custom section "producers", size 114</span>
 <span class="c1">;; features section: mutable-globals, nontrapping-float-to-int, bulk-memory, sign-ext, reference-types, multivalue, bulk-memory-opt, call-indirect-overlong</span>
<span class="p">)</span></code></pre>
</div>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. You <em>should</em> use cargo binstall &#8230;&#8203; as a drop-in replacement for cargo install, as <a href="https://github.com/cargo-bins/cargo-binstall">cargo-binstall</a> is a LOT faster in most circumstances and will still revert to compiling from source if the pre-compiled binaries aren&#8217;t available.
</div>
<div class="footnote" id="_footnotedef_2">
<a href="#_footnoteref_2">2</a>. See: <a href="https://rustwasm.github.io/book/reference/code-size.html#why-care-about-code-size" class="bare">https://rustwasm.github.io/book/reference/code-size.html#why-care-about-code-size</a> for more information.
</div>
<div class="footnote" id="_footnotedef_3">
<a href="#_footnoteref_3">3</a>. WAT or WebAssembly Text Format is like an assembly version of your .wasm binary, see the <a href="#addendum">Addendum</a> for an example from this blog post.
</div>
<div class="footnote" id="_footnotedef_4">
<a href="#_footnoteref_4">4</a>. <a href="https://en.wikipedia.org/wiki/Interprocedural_optimization">Wikipedia</a> and <a href="https://llvm.org/docs/LinkTimeOptimization.html">the LLVM LTO page</a> have more info about what LTO does. In short, a lot and there&#8217;s a good case to be made that <em>all</em> production software should have LTO enabled.)
</div>
<div class="footnote" id="_footnotedef_5">
<a href="#_footnoteref_5">5</a>. Our final result may have slightly worse performance (or it might not).
</div>
</div>]]></content><author><name>Holland Gibson</name></author><category term="2026" /><category term="software" /><category term="rust" /><category term="web" /><summary type="html"><![CDATA[Creating WASM on the web with rust is easy.]]></summary></entry><entry><title type="html">Where are they?</title><link href="https://blog.hollandgibson.com/2025/01/30/we-should-have-this-by-now.html" rel="alternate" type="text/html" title="Where are they?" /><published>2025-01-30T00:00:00+00:00</published><updated>2025-01-30T00:00:00+00:00</updated><id>https://blog.hollandgibson.com/2025/01/30/we-should-have-this-by-now</id><content type="html" xml:base="https://blog.hollandgibson.com/2025/01/30/we-should-have-this-by-now.html"><![CDATA[<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#intro">Intro</a></li>
<li><a href="#ast_aware_code_revision_control">AST-aware code revision control</a>
<ul class="sectlevel2">
<li><a href="#what_we_currently_have">What we currently have</a></li>
<li><a href="#ast_aware">AST-aware</a></li>
</ul>
</li>
<li><a href="#better_formal_methods">Better formal methods</a></li>
<li><a href="#dependency_capability_limits">Dependency capability limits</a></li>
<li><a href="#bonus_clocks">Bonus - Clocks</a></li>
</ul>
</div>
<div class="sect1">
<h2 id="intro">Intro</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It&#8217;s 2025<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup>, and there are a number of problems that seem tractable but somehow we haven&#8217;t solved them yet.
This is especially true when it comes to tools and processes.
You can think of this post as sort of my wishlist, because I don&#8217;t quite have the time to fix any of them myself.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="ast_aware_code_revision_control">AST-aware code revision control</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="what_we_currently_have">What we currently have</h3>
<div class="paragraph">
<p>Git 1.0.0 was released <a href="https://lwn.net/Articles/165127/">in 2005</a>, subversion&#8217;s 1.0.0 <a href="https://en.wikipedia.org/wiki/Apache_Subversion">in 2004</a>, and mercurial&#8217;s 1.0 <a href="https://wiki.mercurial-scm.org/WhatsNew/Archive#Version_1.0_-_2008-03-24">in 2008</a>.
Those 3 version/revision control systems represent essentially all (&gt;98%) professional developers<sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup>.
There are a few promising new tools, but they haven&#8217;t changed the way we reason about changes.</p>
</div>
<div class="paragraph">
<p>There&#8217;s <a href="https://pijul.org/">Pijul</a> which is patch-based, rather than snapshot based like the "main three" above.
This improves how to understand how the tool internally represents the state of code and changes, but doesn&#8217;t fundamentally change anything.</p>
</div>
<div class="paragraph">
<p>Meta/Facebook released (GPLv2) their internal VCS (version control system) tool, <a href="https://github.com/facebook/sapling">Sapling</a>, which is the result of supercharging mercurial to work in a top-down, monolithic (monorepo) collection of a very large amount of code.
Facebook apparently uses a giant monorepo, and at their scale Git or Mercurial just wouldn&#8217;t cut it.<sup class="footnote">[<a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote.">3</a>]</sup>
They (like many modern alternatives to git) also added some quality of life improvements, namely around conflict resolution, speed, and fixing accidents.footnote[See Meta&#8217;s <a href="https://engineering.fb.com/2022/11/15/open-source/sapling-source-control-scalable/">2022 blog post about Sapling</a> for more details.
While I welcome improving the UX of Git, this is still just an iterative improvement.</p>
</div>
<div class="paragraph">
<p>Then there&#8217;s <a href="https://www.fossil-scm.org/home/doc/trunk/www/index.wiki">Fossil</a>, which is like a self-hosted GitHub-lite or Gitea except that the versioning control applies to tickets, wiki, docs, etc rather than <em>just</em> the code.
I&#8217;m a big proponent of putting everything in version control<sup class="footnote">[<a id="_footnoteref_4" class="footnote" href="#_footnotedef_4" title="View footnote.">4</a>]</sup> so that is closer to a fundamental shift, but there&#8217;s nothing stopping you from doing all that tracking in plain-text in your git repo right now. Additionally Fossil tracks changes much more like a database tracks changes: atomic and consistent (i.e. cannot be revised). Small wonder the most famous user of Fossil is SQLite.</p>
</div>
<div class="paragraph">
<p>There are other tools like <a href="https://github.com/jj-vcs/jj">Jujutsu</a>, or <a href="https://github.com/breezy-team/breezy">Breezy</a> and others, but they all appear to focus on git-compatibility or some combination of the "main three" I listed above.</p>
</div>
</div>
<div class="sect2">
<h3 id="ast_aware">AST-aware</h3>
<div class="paragraph">
<p>All modern code can be represented as an abstract syntax tree (AST), and some tools like <a href="https://github.com/tree-sitter/tree-sitter">tree-sitter</a> exist to create that tree in just about all languages people are writing code in.
Why then, is there not a VCS that operates on those constructs rather than the strings or bytes that the code lives on disk as?</p>
</div>
<div class="paragraph">
<p>For example, this code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="rust"><span class="k">const</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="k">const</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">let</span> <span class="n">a</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">5</span><span class="p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>roughly becomes:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/diag-d2-md5-82ef58636e4f1adecd162a5097f8a104.svg" alt="Diagram" width="553" height="1028">
</div>
</div>
<div class="paragraph">
<p>Combining an AST with some additional metadata (for organizing and readability) and a strong, automatic formatter should result in consistent code without requiring completely new Integrated Developer Editors (IDEs).
Although I would expect the advent of AST-aware VCS to also motivate the creation of AST-targeted IDEs that operate on the tree rather than files on disk too.
Code could be consistently "rendered" to a bunch of source files, etc.
Changes would be tracked much closer to what the language understands rather than what changes on disk.</p>
</div>
<div class="paragraph">
<p>Just look at what the diff or patch looks like when <a href="https://github.com/psf/requests/commit/eeafdc143bee0f0356e0f5115029eaef792d4eb4">moving code to a new file</a><sup class="footnote">[<a id="_footnoteref_5" class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup>, or when  <a href="https://softwareengineering.stackexchange.com/questions/362906/variable-renaming-throughout-solution-will-produce-lots-of-noise-in-git-blame-w">trying to rename a variable</a> resulting in the conversation degrading to "you&#8217;re holding it wrong".</p>
</div>
<div class="paragraph">
<p>We have the technology now, so where is it?</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="better_formal_methods">Better formal methods</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="/assets/images/20250130-dan-cristian-padure-h3kuhYUCE9A-unsplash.min.jpg" alt="A blackboard full of diagrams and equations written in chalk.">
</div>
<div class="title">Photo by <a href="https://unsplash.com/@dancristianpaduret?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Dan Cristian Pădureț</a> on <a href="https://unsplash.com/photos/a-blackboard-with-a-bunch-of-diagrams-on-it-h3kuhYUCE9A?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></div>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>Formal methods are fantastic for eliminating errors.
They are truly amazing if you can work in the way that works best with formal methods.
You can either write the mathematical proofs first, and generate the code.
Or, you can write your proofs/contracts alongside your code and (usually with some extra help from you) get the theorem prover to give you a certificate of correctness.</p>
</div>
<div class="paragraph">
<p>Formal methods can give a very high degree of certainty that your software will perform correctly (although speed/efficiency is not addressed).
Their use in critical applications like avionics or security libraries is a boon for all of us.
Unfortunately formal methods aren&#8217;t user friendly enough.<sup class="footnote">[<a id="_footnoteref_6" class="footnote" href="#_footnotedef_6" title="View footnote.">6</a>]</sup>
Using formal methods requires learning at least new ways of writing out your proofs alongside or instead of your code and interactively generating proofs on existing code is not feasible right now.</p>
</div>
<div class="paragraph">
<p>What I want is to be able to specify the contracts of each function using the programming language, and having the compiler or some sort of helper give guarantees and ensure correctness without having to jump through hoops.
Things like bounded-numbers, strong-typing, semantic<sup class="footnote">[<a id="_footnoteref_7" class="footnote" href="#_footnotedef_7" title="View footnote.">7</a>]</sup> or refined types are available now but not always all in the same language<sup class="footnote">[<a id="_footnoteref_8" class="footnote" href="#_footnotedef_8" title="View footnote.">8</a>]</sup>. and they aren&#8217;t enough yet.
Perhaps LLMs can help with this, so I have a bit more hope that formal methods can become easier to use.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dependency_capability_limits">Dependency capability limits</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="/assets/images/20250130-wesley-tingey-snNHKZ-mGfE-unsplash.min.jpg" alt="Stacks and stacks of paperwork.">
</div>
<div class="title">Photo by <a href="https://unsplash.com/@wesleyphotography?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Wesley Tingey</a> on <a href="https://unsplash.com/photos/stack-of-books-on-table-snNHKZ-mGfE?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></div>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>Transitive dependencies are a security nightmare<sup class="footnote">[<a id="_footnoteref_9" class="footnote" href="#_footnotedef_9" title="View footnote.">9</a>]</sup>.
Between the <code>xz</code> supply chain attack and npm&#8217;s <code>left-pad</code> incident, there is much to fear when it comes to the security of your software supply chain.
However, the absolutely huge performance bonus you get from using well-managed and well-optimized libraries are too important to leave behind.
So what then?</p>
</div>
<div class="paragraph">
<p>Why then, can we not limit the capabilities of dependencies?
I would love to say in (i.e. configure) my <code>Cargo.toml</code> to prohibit the <a href="https://docs.rs/reqwest/latest/reqwest/">reqwest</a> crate from accessing the disk and prohibit the <a href="https://docs.rs/serde/latest/serde/index.html">serde</a> crate from doing anything on the network.
Even better, it would be amazing to fully specify the limits to the dependencies <em>from my code</em> to a highly precise degree, like compile time guarantees that the disk access is read-only in a specific spot, or sandbox, etc.</p>
</div>
<div class="paragraph">
<p>We have things like <code>wasm</code> that are a start, but they don&#8217;t give you any control besides giving you a relatively safe sandbox to run other people&#8217;s code in.</p>
</div>
<div class="paragraph">
<p>This gets a little complicated because the problem of someone linking to another binary or writing assembly, both of which have appropriate uses, can be used to bypass via obfuscation most checks I would think of being possible currently.
I think a new high-level language is needed to demonstrate how nice this could be.
A language where the capabilities are detected by the compiler and clearly (automatically) documented so automated enforcement is possible.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bonus_clocks">Bonus - Clocks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Ok this isn&#8217;t really something that will help a software developer, but I am frustrated that so many clocks are out of sync.
Between kitchen appliances, wall clocks, car clocks, etc I just assume that they are +/- a few minutes of the actual time.
Why are we still setting clocks manually?
I own a radio-synchronized wrist-watch<sup class="footnote">[<a id="_footnoteref_10" class="footnote" href="#_footnotedef_10" title="View footnote.">10</a>]</sup>, some radio synchronized wall clocks, some GPS-synced clocks but getting anything remotely nice in any device that provides it&#8217;s own clock is extremely difficult.
I mean $1000 ovens can&#8217;t even be bothered to put a quartz oscillator for their clock<sup class="footnote">[<a id="_footnoteref_11" class="footnote" href="#_footnotedef_11" title="View footnote.">11</a>]</sup>!</p>
</div>
<div class="paragraph">
<p>it&#8217;s been over 60 years since WWVB (<a href="https://en.wikipedia.org/wiki/WWVB">the NIST time clock for the US/Cananda</a>) officially launched and 45 ish years since GPS was available to civilians.
Why aren&#8217;t these more available and just included in things?</p>
</div>
<div class="paragraph">
<p>The main problem I see is that there&#8217;s no cheap, accurate, reliable way to get time signals - GPS and WWVB (or equivalent) don&#8217;t work super well through walls, after all.
But we all (mostly) have WiFi.
Surely there&#8217;s space in the access point beacons<sup class="footnote">[<a id="_footnoteref_12" class="footnote" href="#_footnotedef_12" title="View footnote.">12</a>]</sup> for adding some world time (a sort of up-time of the WiFi access point is already present) to those packets.
That way you could get internet time without ever connecting to the internet!</p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. or 12,025 HCE
</div>
<div class="footnote" id="_footnotedef_2">
<a href="#_footnoteref_2">2</a>. In <a href="https://survey.stackoverflow.co/2022/#version-control-version-control-system-prof">StackOverflow&#8217;s 2022 Developer Survey</a> only 1.38% of "professional developers" don&#8217;t use Git, SVN, or Mercurial as their primary version control
</div>
<div class="footnote" id="_footnotedef_3">
<a href="#_footnoteref_3">3</a>. To be fair, Git was designed for an email, patch-based workflow well before anyone had ever coined the term 'monorepo'.
</div>
<div class="footnote" id="_footnotedef_4">
<a href="#_footnoteref_4">4</a>. Someday I&#8217;ll explain
</div>
<div class="footnote" id="_footnotedef_5">
<a href="#_footnoteref_5">5</a>. This is not the <em>best</em> example because the filenames are de-facto modules in python and this technically results in a different structure, but there is no real change because a test got moved from one file to another. The function itself is the same, but git can only see them as completely separate changes.
</div>
<div class="footnote" id="_footnotedef_6">
<a href="#_footnoteref_6">6</a>. Hillel Wayne in his formal methods <a href="https://www.hillelwayne.com/post/business-case-formal-methods/#why-not-use-formal-methods">blog post</a> lists great reasons why formal methods don&#8217;t work.
</div>
<div class="footnote" id="_footnotedef_7">
<a href="#_footnoteref_7">7</a>. Or <a href="https://www.twosigma.com/articles/semantic-types-from-computer-centric-to-human-centric-data-types/">"human-centric types"</a>
</div>
<div class="footnote" id="_footnotedef_8">
<a href="#_footnoteref_8">8</a>. I&#8217;m aware of some refined types in rust, like <a href="https://docs.rs/uom/0.26.0/uom/index.html">uom</a> but not language-wide constructs
</div>
<div class="footnote" id="_footnotedef_9">
<a href="#_footnoteref_9">9</a>. Laurence Tratt gives an exquisite analysis of this problem on <a href="https://tratt.net/laurie/blog/2024/can_we_retain_the_benefits_of_transitive_dependencies_without_undermining_security.html">his blog</a>. I definitely took some inspiration from that post here
</div>
<div class="footnote" id="_footnotedef_10">
<a href="#_footnoteref_10">10</a>. A Casio LCW-M100TS, an amazing watch
</div>
<div class="footnote" id="_footnotedef_11">
<a href="#_footnoteref_11">11</a>. They just use the mains frequency, which is not very precise
</div>
<div class="footnote" id="_footnotedef_12">
<a href="#_footnoteref_12">12</a>. There&#8217;s a whole <a href="https://datatracker.ietf.org/doc/html/rfc5415#section-4.6.39">vendor-specific payload</a> section to the 802.11 beacon frames, and clearly plenty of room to put a time signal. An access point could emit a beacon, say once a minute, containing the linux epoch and most devices could ignore it, but clocks could listen for that beacon and correct their clock.
</div>
</div>]]></content><author><name>Holland Gibson</name></author><category term="2025" /><category term="tech" /><summary type="html"><![CDATA[The software industry is being held back without these tools.]]></summary></entry><entry><title type="html">How to be a parent (or loved one) in the hospital</title><link href="https://blog.hollandgibson.com/2024/11/20/being-a-parent-in-the-hospital.html" rel="alternate" type="text/html" title="How to be a parent (or loved one) in the hospital" /><published>2024-11-20T00:00:00+00:00</published><updated>2024-11-20T00:00:00+00:00</updated><id>https://blog.hollandgibson.com/2024/11/20/being-a-parent-in-the-hospital</id><content type="html" xml:base="https://blog.hollandgibson.com/2024/11/20/being-a-parent-in-the-hospital.html"><![CDATA[<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#things_the_providers_dont_do">Things the providers don&#8217;t do</a>
<ul class="sectlevel2">
<li><a href="#not_coordinating_with_other_teams">Not coordinating with other teams</a></li>
<li><a href="#checking_for_new_notes_after_rounds">Checking for new notes after rounds</a></li>
<li><a href="#putting_the_patient_first">Putting the patient first</a></li>
</ul>
</li>
<li><a href="#things_you_canshould_do">Things you can/should do</a></li>
<li><a href="#parting_notes">Parting notes</a></li>
</ul>
</div>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Something is wrong.
You don&#8217;t know why your love is crying.
They&#8217;re feeling worse and worse and you can&#8217;t make it better.
In a panic you bring them to the emergency department, wait too long to get seen, and finally get taken to a sterile, but busy area.
A few people with stethoscopes ask a lot of questions, and thank goodness, it wasn&#8217;t just you.
Something is wrong and they say they&#8217;re going to figure it out.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/20241120-jc-gellidon-9Eb-bpTXglM-unsplash.jpg" alt="Active ICU room, many doctors and nurses wearing masks standing over a patient">
</div>
<div class="title">Photo by <a href="https://unsplash.com/@jcgellidon?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">JC Gellidon</a> on <a href="https://unsplash.com/photos/doctor-performing-operation-9Eb-bpTXglM?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></div>
</div>
<hr>
<div class="paragraph">
<p>You&#8217;d think being the in a hospital would mean having lots of people take care of you so the only thing you have to worry about is following instructions and making sure the rest of your life doesn&#8217;t fall apart.
In my experience, this is only part of the deal.</p>
</div>
<div class="paragraph">
<p>Having spent close to 90 days (and most of those nights) in the hospital as a healthy parent of a sick child over the last year or so, I&#8217;ve started jotting down reminders on all the things that I need to do while in the hospital.</p>
</div>
<div class="paragraph">
<p>I hope this post helps anyone who finds themselves or is with someone in the hospital and helps you get the best treatment possible.</p>
</div>
<div class="paragraph">
<p>Of course these are only my experiences, but we were at the best children&#8217;s hospital in the state, one that happens to be tied to an R-1 research university as well.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="things_the_providers_dont_do">Things the providers don&#8217;t do</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>coordinate with other teams</p>
</li>
<li>
<p>check for new notes after rounds</p>
</li>
<li>
<p>think very hard about patient-comfort</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="not_coordinating_with_other_teams">Not coordinating with other teams</h3>
<div class="paragraph">
<p>I had naively assumed that the providers and professionals in the pediatric ICU would be a well-oiled machine that worked hand-in-hand with their counterparts: the cardiology team talked to the neurology team, and the charge nurse knew both of their updates.</p>
</div>
<div class="paragraph">
<p>I think that the providers (doctors, nurse practitioners, nurses, therapists, etc) each work on finding solutions to things that they are uniquely educated to do.
Of course there is a lot of overlap in their expertise.
As an example: despite it being something the nurses do more often, just about any provider can (and will) adjust the air flow to the
<a href=""><a href="https://en.wikipedia.org/wiki/Nasal_cannula">nasal cannula</a></a>
as needed.
That doesn&#8217;t mean that they all are trying to do the same thing.</p>
</div>
<div class="paragraph">
<p>One team may be focused on reducing the dependence on the "low flow" oxygen support, while another may be trying to keep all the stats (heart rate, blood pressure, O<sub>2</sub> sats, etc) in a good place so the patient can recover enough for a big upcoming event, for example.</p>
</div>
<div class="paragraph">
<p>The system generally in place to get everyone in sync is "rounds."
This is where at least 1 representative from every team is present to coordinate on the plan of care.
The problem with this system is that one cannot be on rounds all day long.
At some point they have to, you know, practice medicine.
Write orders, review results of tests and all that other stuff.</p>
</div>
<div class="paragraph">
<p>In-between rounds, as lab results come in and stats change, the plan rightfully adjusts.
However, this is where the discrepancies originate.
Which leads me to the next point:</p>
</div>
</div>
<div class="sect2">
<h3 id="checking_for_new_notes_after_rounds">Checking for new notes after rounds</h3>
<div class="paragraph">
<p>Generally, the providers review notes prior-to rounds, during rounds, and when they are expecting something (like the results of the ultrasound they ordered).
A part of practicing modern medicine (I think, at least) is do record notes after every update in the computer system.
This gives a very robust, high fidelity record of the treatment and plan for any patient.
Any provider can log in to see everyone&#8217;s notes.
A new specialist can get called and know most of what they need to know before they even get to the room!</p>
</div>
<div class="paragraph">
<p>However, just like a provider can&#8217;t spend all day on rounds, they can&#8217;t spend all day reading and writing notes (not to mention that the hospital can&#8217;t directly bill the time spent writing/reading notes - but that is a discussion point for another time).
So, an individual coming in may not know everything they might want to know.
Or worse, may have missed rounds for one reason or another and may be actively trying to achieve something counter-productive to the plan.</p>
</div>
<div class="paragraph">
<p>The plan can change on a dime with just one test result or one new symptom.
But when all they think about is tackling the "problem" they sometimes can forget about the patient.</p>
</div>
</div>
<div class="sect2">
<h3 id="putting_the_patient_first">Putting the patient first</h3>
<div class="paragraph">
<p>I won&#8217;t belabor this point.
"Patient-first" care is the standard way of practicing medicine in the USA.
Sometimes though, the small things just aren&#8217;t as important to the people trying to solve the bigger problems.</p>
</div>
<div class="paragraph">
<p>They don&#8217;t know when the pain is getting worse, or how long it&#8217;s been since the patient last had a meal or got to sleep.
This is another, perhaps more specific to my experience, problem. The hospital makes it very difficult to get sleep or eat well.
Try doing those things poorly during normal times and see how you feel.
Now imagine being in a lot of pain, and adding that discomfort to the list.
Eating and sleeping right are pivotal to recovery and there are often small changes that can be done to vastly improve the experience at the hospital.
For example, waking up to get weighed at 3am because that&#8217;s a better time for the nurse is completely unacceptable, that can wait.</p>
</div>
<div class="paragraph">
<p>OK so knowing all this, what can we do?</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="things_you_canshould_do">Things you can/should do</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>back-brief<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup> each provider</p>
</li>
<li>
<p>ask about 1.5 times as many questions as you think you need to</p>
</li>
<li>
<p>advocate for the patient</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The good news is that a non-patient (you or another loved one) in the room can help cover these gaps and improve the care the patient gets.
My strategy was to try to learn as much as possible about the plan of care and be vocal whenever I wasn&#8217;t sure they were doing the right thing.</p>
</div>
<div class="paragraph">
<p>It is hard to be an advocate (for me at least) when you have dozens of people with decades of time spent learning/practicing medicine saying things confidently.
However, as the parent of a patient (or you if you are the patient) you are ultimately the one who has the authority to reject any treatment they give you.
I didn&#8217;t have any moral or religious qualms with any of the treatments suggested in our hospital stays, and I don&#8217;t think I ever outright rejected a treatment they recommended.</p>
</div>
<div class="paragraph">
<p>I asked a lot of questions to understand, and asked a few questions to make sure the provider knew what the other provider (that probably left just minutes ago) told me.
More than a few times, the provider changed what they were doing after that.
Most of the time, they were polite and confirmed that they knew what I was talking about.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="parting_notes">Parting notes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>I spent all this time focusing on gaps and problems that can happen on a hospital stay.
I have the utmost respect for the professionals who spend their lives trying to help others get well.
They will make much more a difference in people&#8217;s lives than the code I&#8217;ve written ever will.
I have never wished that our providers had more experience or were better at what they do, but that doesn&#8217;t mean that there aren&#8217;t ways to improve the treatment for someone you love.</p>
</div>
<div class="paragraph">
<p>If you follow absolutely none of this advice, you will probably still have a satisfactory experience at the hospital.
But if given the chance to get your loved one better care, wouldn&#8217;t you?
Some of this advice may be useless or worse in a situation you find yourself in, so you should also exercise judgment in following them too.
Good luck!
I hope you never find yourself in the position to learn these things first hand, but if you do - if I can help, believe me you can too.</p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. I use the Army&#8217;s definition of this as they describe it in their "Mission Command" publications. Essentially, you explain to the presenter (probably the most senior person present) what you understand their plan/briefing to be - proving you understood what they described to you
</div>
</div>]]></content><author><name>Holland Gibson</name></author><category term="2024" /><category term="life" /><summary type="html"><![CDATA[There is a lot to do when you aren&#8217;t in charge.]]></summary></entry></feed>