<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://shashwatak.github.io/satellite-js/blog</id>
    <title>🛰️ Satellite.js Blog</title>
    <updated>2026-03-11T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://shashwatak.github.io/satellite-js/blog"/>
    <subtitle>🛰️ Satellite.js Blog</subtitle>
    <icon>https://shashwatak.github.io/satellite-js/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[WASM: Making the Fastest SGP4 for the web]]></title>
        <id>https://shashwatak.github.io/satellite-js/blog/wasm</id>
        <link href="https://shashwatak.github.io/satellite-js/blog/wasm"/>
        <updated>2026-03-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[If you tried running this, you know the results: slowdowns which are not suitable for realtime applications.]]></summary>
        <content type="html"><![CDATA[<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> now </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> results </span><span class="token operator">=</span><span class="token plain"> entireSatelliteDatabase</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">satRec </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">propagate</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">satRec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> now</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>If you tried running this, you know the results: slowdowns which are not suitable for realtime applications.</p>
<p>This is where we went for a mission to make the <strong>fastest theoretically possible SGP4/SDP4 implementation</strong> available in JavaScript. Meet WebAssembly and <em>a lot</em> of optimization techniques under the hood.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://shashwatak.github.io/satellite-js/blog/wasm#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h2>
<p>The Satellite.js library has originally started as a port of the <a href="https://pypi.org/project/sgp4/" target="_blank" rel="noopener noreferrer" class="">Python sgp4 library</a>, which in turn has its roots in <a href="https://github.com/CelesTrak/fundamentals-of-astrodynamics" target="_blank" rel="noopener noreferrer" class="">the C++ code by David Vallado</a>. The library is pure calculations - and it's exactly one of the main use cases for WASM.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="prior-art">Prior art<a href="https://shashwatak.github.io/satellite-js/blog/wasm#prior-art" class="hash-link" aria-label="Direct link to Prior art" title="Direct link to Prior art" translate="no">​</a></h2>
<p>There were at least 2 previous attempts to make SGP4 on WASM, one of which was never open-sourced, and the second, Rust-based, was apparently abandoned a few years ago due to the worse performance than expected.</p>
<p>One of the hard parts about WASM is: <strong>you can only pass numbers between WASM and JS</strong>. You can't simply pass Objects and Arrays between the JS and the WebAssembly worlds with no overhead.</p>
<blockquote>
<p>But there are accessible and easy options to serialize objects and other data and still pass it into WASM!</p>
</blockquote>
<p>Yes. Here's what comes next though: the overhead of serialization suddenly <strong>outweighs</strong> the performance benefits of calculating in WASM. A developer who tried to push for performance suddenly sees a <em>worse</em> performance than that of JS and abandons the idea.</p>
<p>But there's more to it: not only your WASM must be fast. It must be faster than what the JS engine achieves when optimizing the JavaScript code. And <strong>JS engines now are incredibly powerful in optimization</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="just-do-less">Just do less<a href="https://shashwatak.github.io/satellite-js/blog/wasm#just-do-less" class="hash-link" aria-label="Direct link to Just do less" title="Direct link to Just do less" translate="no">​</a></h2>
<p>That's the simplest idea of optimization: literally, spend less cycles of the user's CPU to achieve the result.</p>
<p>Here's how we do it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-no-javascript-overhead">1. No JavaScript overhead<a href="https://shashwatak.github.io/satellite-js/blog/wasm#1-no-javascript-overhead" class="hash-link" aria-label="Direct link to 1. No JavaScript overhead" title="Direct link to 1. No JavaScript overhead" translate="no">​</a></h2>
<p>The pure JavaScript <code>sgp4</code> function does pure JavaScript things, such as it constructs a few JS objects which have to be garbage collected. Modern engines are able to optimize intermediate objects away, but it doesn't happen consistently. The more stuff you do besides simply SGP4, such as you transform coordinates, calculate shadow status etc, the more likely it is that engine optimization fails somewhere.</p>
<p>In our tests we had nearly identical JS code, calculating exactly the same thing, differing by 5x to 10x in performance.</p>
<p>The C++ version does the identical math but writes directly into <strong>pre-allocated flat arrays</strong>:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mrt </span><span class="token operator">*</span><span class="token plain"> ux</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> satrec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">radiusearthkm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mrt </span><span class="token operator">*</span><span class="token plain"> uy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> satrec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">radiusearthkm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">mrt </span><span class="token operator">*</span><span class="token plain"> uz</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> satrec</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">radiusearthkm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>Zero object allocation means no dependence on a JS engine figuring out optimization every time and more consistent run times.</p>
<p>The same applies to all transforms. Every JS transform function - <code>eciToEcf</code>, <code>eciToGeodetic</code>, <code>ecfToLookAngles</code> - returns a new JS object. The C++ equivalents write into flat <code>double</code> arrays in-place.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-no-translation-of-values-between-wasm-and-c-side">2. No translation of values between WASM and C++ side<a href="https://shashwatak.github.io/satellite-js/blog/wasm#2-no-translation-of-values-between-wasm-and-c-side" class="hash-link" aria-label="Direct link to 2. No translation of values between WASM and C++ side" title="Direct link to 2. No translation of values between WASM and C++ side" translate="no">​</a></h2>
<p>A common pitfall of WASM integration is costly marshalling at the JS-WASM boundary. We avoid this entirely.</p>
<p>The key innovation: our C++ code <strong>generates a JSON description of its own struct layout</strong> at runtime - field names, byte offsets, types, and sizes, which looks like this:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// [field name, type, offset, size]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"inclo"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"double"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">760</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"nodeo"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"double"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">768</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"ecco"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"double"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">776</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"argpo"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"double"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">784</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token number">8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...for all ~80 fields</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></span></code></pre></div></div>
<p>This layout is queried <strong>once</strong> at runtime creation. Then the JS side <strong>directly writes SatRec objects into C++ structs in WASM heap memory</strong> using <code>DataView</code>. <code>DataView.setFloat64</code>, <code>setInt32</code>, <code>setInt8</code> - field values are placed where C++ struct expects them. <strong>No serialization, no JSON, no marshalling.</strong></p>
<p>The same approach is used for a struct called <code>RunData</code> which carries options such as input/output pointers, enabled calculators and their settings, during a <code>run()</code> call.</p>
<p><strong>Reading results is zero-copy too.</strong> Calculator <code>getRawOutput()</code> methods return <code>TypedArray</code> views directly on WASM heap memory:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">getRawOutput</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    position</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Float64Array</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">module</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HEAP8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">outputPointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> outputSize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    velocity</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Float64Array</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">module</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HEAP8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    error</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Int8Array</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">this</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">module</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HEAP8</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">buffer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>These are <strong>views</strong>, not copies, on WASM linear memory.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-minimal-memory-allocation-maximum-reuse">3. Minimal memory allocation, maximum reuse<a href="https://shashwatak.github.io/satellite-js/blog/wasm#3-minimal-memory-allocation-maximum-reuse" class="hash-link" aria-label="Direct link to 3. Minimal memory allocation, maximum reuse" title="Direct link to 3. Minimal memory allocation, maximum reuse" translate="no">​</a></h2>
<p>Push a full LookAngles pipeline through, as of time of writing, entire database of over 30 000 satellites, and you're looking at allocating and collecting <strong>hundreds of thousands of objects</strong>.</p>
<p>The WASM path takes a different approach: <strong>allocate everything once, reuse across every run.</strong></p>
<p><code>BulkPropagator</code>'s constructor allocates exactly three things:</p>
<ol>
<li class="">A satellite struct array (one allocation for all satellites)</li>
<li class="">A dates array (one allocation for all timestamps)</li>
<li class="">A <strong>single contiguous output buffer</strong> for all calculators</li>
</ol>
<p>It then partitions this single buffer among calculators using byte offsets.</p>
<p>On subsequent <code>run()</code> calls: <strong>zero new allocations</strong>. The same buffers are overwritten. Re-allocation only happens if array sizes grow beyond the original capacity - and even then, it's a single <code>free</code> + <code>malloc</code> pair.</p>
<p><code>BulkPropagator</code> implements <code>Disposable</code> and supports the new <code>using</code> syntax for the users to dispose of it conveniently.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-single-instruction-multiple-data">4. Single Instruction Multiple Data<a href="https://shashwatak.github.io/satellite-js/blog/wasm#4-single-instruction-multiple-data" class="hash-link" aria-label="Direct link to 4. Single Instruction Multiple Data" title="Direct link to 4. Single Instruction Multiple Data" translate="no">​</a></h2>
<p>Since propagations can be highly parallel (each SatRec can be computed independently), and further coordinate transforms (ECI → ECF → LookAngles etc) are completely independent, there are huge potential benefits to have from Single Instruction Multiple Data (SIMD further down).</p>
<p>A recap on SIMD: to the existing <code>i32</code>, <code>i64</code>, <code>f32</code>, <code>f64</code> types it adds <code>v128</code> type, which is a 128-bit vector where you can pack, for example, 4 32-bit values, or 2 64-bit ones. You can create two of these and then use an instruction that multiplies the values in them. This means that, for 64-bit values, you can do 2 multiplications in one CPU cycle; and for 32-bit values - 4 multiplications, at once. There are a bunch of interpretations of <code>v128</code> vectors and instructions of them available and already implemented for WASM.</p>
<p>All our WASM builds are compiled with WebAssembly 128-bit SIMD instructions. The LLVM compiler auto-vectorizes loops where possible.</p>
<p>The transform functions - ECF conversion, GMST, LookAngles, DopplerFactor - all iterate over contiguous flat <code>double</code> arrays with simple arithmetic. These are ideal candidates for auto-vectorization. We also enable vectorization reporting (<code>-Rpass=loop-vectorize</code>) in our builds to verify what the compiler actually vectorizes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-loop-invariant-code-optimization">5. Loop invariant code optimization<a href="https://shashwatak.github.io/satellite-js/blog/wasm#5-loop-invariant-code-optimization" class="hash-link" aria-label="Direct link to 5. Loop invariant code optimization" title="Direct link to 5. Loop invariant code optimization" translate="no">​</a></h2>
<p>Processing arrays of satellites and dates opens multiple opportunities to identify code, which doesn't really depend on each satellite and each date. This code can then be called just once per its actual dependency. For example, if it depends on just dates and you compute 30 000 satellites for 1 date - you only calculate it once.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="date-conversion">Date conversion<a href="https://shashwatak.github.io/satellite-js/blog/wasm#date-conversion" class="hash-link" aria-label="Direct link to Date conversion" title="Direct link to Date conversion" translate="no">​</a></h3>
<p>In the JS path, <code>propagate()</code> calls <code>jday(date)</code> on every invocation to convert a <code>Date</code> to Julian day. For <strong>N</strong> satellites and <strong>M</strong> dates, that's <strong>N*M</strong> <code>jday()</code> calls.</p>
<p>In the WASM path, <code>writeDatesArray</code> converts each date to Julian day <strong>once</strong> and writes it directly into WASM memory:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">dates</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">forEach</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  module</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">HEAPF64</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">startOffset </span><span class="token operator">+</span><span class="token plain"> index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">jday</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>Here in WASM, Julian day is the first class citizen.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="observer-position">Observer position<a href="https://shashwatak.github.io/satellite-js/blog/wasm#observer-position" class="hash-link" aria-label="Direct link to Observer position" title="Direct link to Observer position" translate="no">​</a></h3>
<p>In JS, <code>ecfToLookAngles</code> calls <code>geodeticToEcf</code> internally - recomputing the observer's ECF position <strong>every single time</strong>:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// This runs inside every ecfToLookAngles call:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">geodeticToEcf</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> longitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> height </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> a </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6378.137</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> b </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6356.7523142</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> f </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">a </span><span class="token operator">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> e2 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">2</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">f </span><span class="token operator">*</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> normal </span><span class="token operator">=</span><span class="token plain"> a </span><span class="token operator">/</span><span class="token plain"> Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">sqrt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e2 </span><span class="token operator">*</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> Math</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>In C++, Look Angles transform computes all of this <strong>once before the loop</strong>:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_look_angles</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> longitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Computed once:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> a </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6378.137</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> b </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6356.7523142</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> f </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">a </span><span class="token operator">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> e2 </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">2</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">f </span><span class="token operator">*</span><span class="token plain"> f</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> normal </span><span class="token operator">=</span><span class="token plain"> a </span><span class="token operator">/</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">sqrt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e2 </span><span class="token operator">*</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> observerEcfX </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">normal </span><span class="token operator">+</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">cos</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">cos</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">longitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> observerEcfY </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">normal </span><span class="token operator">+</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">cos</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">longitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">double</span><span class="token plain"> observerEcfZ </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">normal </span><span class="token operator">*</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">1</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> e2</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">*</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">sin</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Then loop over all satellites * dates:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> i </span><span class="token operator">=</span><span class="token plain"> satellites_start</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> i </span><span class="token operator">&lt;</span><span class="token plain"> satellites_end</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> i</span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">int</span><span class="token plain"> j </span><span class="token operator">=</span><span class="token plain"> dates_start</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> j </span><span class="token operator">&lt;</span><span class="token plain"> dates_end</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> j</span><span class="token operator">++</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...use precomputed observerEcf values</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>There are a few such examples.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-one-wasm-boundary-crossing-for-the-full-pipeline">6. One WASM boundary crossing for the full pipeline<a href="https://shashwatak.github.io/satellite-js/blog/wasm#6-one-wasm-boundary-crossing-for-the-full-pipeline" class="hash-link" aria-label="Direct link to 6. One WASM boundary crossing for the full pipeline" title="Direct link to 6. One WASM boundary crossing for the full pipeline" translate="no">​</a></h2>
<p>In the JS path, computing LookAngles for one satellite at one date requires calling separate functions: <code>propagate()</code>, <code>gstime()</code>, <code>eciToEcf()</code>, <code>ecfToLookAngles()</code>.</p>
<p>The WASM path makes <strong>one call</strong>. The C++ <code>compute()</code> function chains every enabled calculation stage in a single invocation:</p>
<div class="language-cpp codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cpp codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">void</span><span class="token plain"> EMSCRIPTEN_KEEPALIVE </span><span class="token function" style="color:rgb(80, 250, 123)">compute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">RunData</span><span class="token operator">*</span><span class="token plain"> __restrict runData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_eci</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">gmstEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">             </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_gmst</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">sunPositionEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">      </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_sun_positions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">ecfPositionEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">      </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_ecf_position_or_velocity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">ecfVelocityEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">      </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_ecf_position_or_velocity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">geodeticPositionEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_geodetic_positions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">lookAnglesEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">       </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_look_angles</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">dopplerFactorEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_doppler_factor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">runData</span><span class="token operator">-&gt;</span><span class="token plain">shadowFractionEnabled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">   </span><span class="token function" style="color:rgb(80, 250, 123)">calculate_shadow_fraction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token comment" style="color:rgb(98, 114, 164)">/* ... */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Intermediate results never leave WASM memory between stages. The ECI output feeds directly into ECF conversion via pointers in the <code>RunData</code> struct - no data copying, no JS objects, no boundary crossings.</p>
<p>This also means <strong>unused stages are free</strong>. Each calculator sets a boolean <code>Enabled</code> flag in <code>RunData</code>. If you don't need geodetic positions or Doppler factor, those branches aren't entered.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cache-friendly-flat-memory-layout">7. Cache-friendly flat memory layout<a href="https://shashwatak.github.io/satellite-js/blog/wasm#7-cache-friendly-flat-memory-layout" class="hash-link" aria-label="Direct link to 7. Cache-friendly flat memory layout" title="Direct link to 7. Cache-friendly flat memory layout" translate="no">​</a></h2>
<p>All WASM outputs are stored in flat contiguous <code>double</code> arrays, indexed as <code>[satellite_index * dates_count + date_index] * 3</code>.</p>
<p>Why does this matter?</p>
<ul>
<li class=""><strong>Cache line friendliness.</strong> Sequential iteration over contiguous memory means the CPU prefetcher can predict and load upcoming data. Minimal cache misses.</li>
<li class=""><strong>No pointer chasing.</strong> In JS, accessing <code>result.position.x</code> requires following 2 pointer indirections through the V8 heap. In WASM, it's a single indexed read from a flat array.</li>
<li class=""><strong>SIMD-friendly.</strong> Contiguous data means SIMD, as explained above.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-multi-threading-via-pthreads">8. Multi-threading via pthreads<a href="https://shashwatak.github.io/satellite-js/blog/wasm#8-multi-threading-via-pthreads" class="hash-link" aria-label="Direct link to 8. Multi-threading via pthreads" title="Direct link to 8. Multi-threading via pthreads" translate="no">​</a></h2>
<p>The multi-thread build partitions the calculations across N threads. Each thread processes its own slice.</p>
<p>The multi-thread runtime is available via <code>createMultiThreadRuntime</code> and requires <code>SharedArrayBuffer</code> (plus the appropriate <code>Cross-Origin-Opener-Policy</code> / <code>Cross-Origin-Embedder-Policy</code> headers in browsers).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="putting-it-all-together">Putting it all together<a href="https://shashwatak.github.io/satellite-js/blog/wasm#putting-it-all-together" class="hash-link" aria-label="Direct link to Putting it all together" title="Direct link to Putting it all together" translate="no">​</a></h2>
<p>Here's a side-by-side summary of what happens when you propagate satellites through a LookAngles pipeline:</p>
<table><thead><tr><th></th><th>Pure JS</th><th>WASM BulkPropagator</th></tr></thead><tbody><tr><td><strong>Execution</strong></td><td>JS JIT-compiled</td><td>WASM from C++</td></tr><tr><td><strong>Object allocations per sat per date</strong></td><td>~4-10+ JS objects</td><td>0 (pre-allocated flat arrays)</td></tr><tr><td><strong>JS-native boundary crossings</strong></td><td>N/A</td><td>1 per <code>run()</code></td></tr><tr><td><strong>SIMD</strong></td><td>None, unless JIT does that</td><td>Auto-vectorized loops</td></tr><tr><td><strong>Multi-threading</strong></td><td>None - up to the user</td><td>Yes - in multi thread build</td></tr><tr><td><strong>Memory layout</strong></td><td>JS objects</td><td>Contiguous arrays, cache-friendly</td></tr><tr><td><strong>Date conversion</strong></td><td>Per satellite per date</td><td>Once per date</td></tr><tr><td><strong>Observer/constants</strong></td><td>Recomputed every call</td><td>Computed once before the loop</td></tr><tr><td><strong>Pipeline integration</strong></td><td>Separate function calls</td><td>Single <code>compute()</code> call</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-results">The results<a href="https://shashwatak.github.io/satellite-js/blog/wasm#the-results" class="hash-link" aria-label="Direct link to The results" title="Direct link to The results" translate="no">​</a></h2>
<p>Speak for themselves. As measured on Node v24.3, here's a benchmark where JIT was able to optimize JavaScript loops:</p>
<p><img decoding="async" loading="lazy" alt="Almost 3x speed up" src="data:image/png;base64,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" width="602" height="109" class="img_ev3q"></p>
<p>Here's where JIT failed and JS execution time jumped up, but WASM stayed just as fast as before:</p>
<p><img decoding="async" loading="lazy" alt="12x difference" src="https://shashwatak.github.io/satellite-js/assets/images/bench-eci-unoptimized-bea8c5dc8a0ef3d9f625c3a9e8080cdd.png" width="602" height="104" class="img_ev3q"></p>]]></content>
        <author>
            <name>Vladyslav Huba</name>
            <uri>https://www.linkedin.com/in/vladyslav-huba-a85b4414b/</uri>
        </author>
    </entry>
</feed>