<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>性能测试 on Tech Snippets - 嵌入式技术笔记</title><link>https://tech-snippets.xyz/tags/%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95/</link><description>Recent content in 性能测试 on Tech Snippets - 嵌入式技术笔记</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 23 Sep 2026 22:05:25 +0800</lastBuildDate><atom:link href="https://tech-snippets.xyz/tags/%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95/index.xml" rel="self" type="application/rss+xml"/><item><title>ESP32-S3 四种执行方式效率对比：原生 / WebAssembly / Lua/Micropython 的 1000 位圆周率对决</title><link>https://tech-snippets.xyz/posts/esp32s3-native-wasm-lua-pi-benchmark-2026/</link><pubDate>Wed, 23 Sep 2026 22:05:25 +0800</pubDate><guid>https://tech-snippets.xyz/posts/esp32s3-native-wasm-lua-pi-benchmark-2026/</guid><description>在同一台 ESP32-S3 上用同一份 Rabinowitz-Wagon spigot 算法，实测原生动态模块、WebAssembly、Lua 与 MicroPython 四种执行方式计算 1000 位圆周率的性能差距。</description><content:encoded><![CDATA[<h2 id="为什么会有这个对比">为什么会有这个对比</h2>
<p>最近在研究ESP32S3的基础系统和应用分离的开发架构，比较常见的应用层主要有这几种&quot;形态&quot;：</p>
<table>
<thead>
<tr>
<th>形态</th>
<th>本质</th>
<th>典型用途</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>原生动态模块(elf)</strong></td>
<td>编译成目标芯片机器码</td>
<td>性能热区、协议栈、编解码</td>
</tr>
<tr>
<td><strong>WebAssembly 应用(wasm)</strong></td>
<td>编译成字节码，由运行时解释执行</td>
<td>沙箱隔离、第三方维护、生态复用</td>
</tr>
<tr>
<td><strong>Lua 脚本(lua)</strong></td>
<td>直接解释源码</td>
<td>热更新、胶水逻辑、低频控制</td>
</tr>
<tr>
<td><strong>Micropython 脚本(py)</strong></td>
<td>直接解释源码</td>
<td>与lua一致</td>
</tr>
</tbody>
</table>
<p>它们共用一个应用包 / 部署 / 加载框架，但运行性能差多少，很少有人用同一把尺子量过。本文就用一个最经典的基准（计算 1000 位圆周率）在同一个设备上给四种形态做了一次公平对决。</p>
<h2 id="测试怎么做到公平">测试怎么做到公平</h2>
<ul>
<li><strong>同一台设备</strong>：ESP32-S3 R8（Xtensa内核，主频 240 MHz，8MB PSRAM, 16MB Flash）</li>
<li><strong>同一种运行环境</strong>：应用都加载到PSRAM执行</li>
<li><strong>同一个算法</strong>：四个实现是同一份 Rabinowitz-Wagon spigot 算法的直译</li>
<li><strong>同一位数</strong>：都算 1000 位，输出结果逐位一致（小数位完全相同）</li>
<li><strong>同一计时口径</strong>：只统计纯计算耗时，不含加载、初始化、日志输出</li>
</ul>
<p>除了micropython直接在官方固件上运行，其他四种测试脚本各自封装成应用包，由设备启动计划自动拉起，开机即跑、跑完即退，互不干扰。</p>
<h2 id="使用的算法rabinowitz-wagon-spigot">使用的算法：Rabinowitz-Wagon spigot</h2>
<p>&ldquo;spigot&rdquo;（水龙头）算法是一类逐位生成 π 的算法，像水龙头一样每拧一下流出一位数字。Rabinowitz-Wagon 是其中最经典的一种：用一组长整数数组做&quot;长除法流水线&quot;，每轮归约出一位。</p>
<p>伪代码（以 1 为下标）：</p>
<pre tabindex="0"><code>输入 n（要生成的位数）
len = floor(10 * n / 3)
a[1..len] 全部初始化为 2
nines = 0, predigit = 0

对 j = 1..n：
    q = 0
    从 i = len 递减到 1：
        x = 10 * a[i] + q * i
        d = 2 * i - 1
        a[i] = x mod d
        q = floor(x / d)
    a[1] = q mod 10
    q = floor(q / 10)

    如果 q == 9：nines = nines + 1
    否则如果 q == 10：
        输出 (predigit + 1)
        连续输出 nines 个 0
        predigit = 0, nines = 0
    否则：
        输出 predigit（第一轮跳过）
        predigit = q
        连续输出 nines 个 9
        nines = 0
最后输出 predigit
</code></pre><blockquote>
<p>技巧：<strong>多算 3 位再截断</strong>。spigot 算法在出现 9 传播时可能&quot;欠一位&quot;，多算几位再丢弃，能保证前 1000 位绝对正确。四个实现都按 <code>n = 1003</code> 计算、取前 1000 位。</p>
</blockquote>
<p>这段算法逻辑很简单，但恰好是纯整数密集计算：没有浮点、没有内存分配热点（只有一组长数组）、没有外部调用，最能拉开&quot;解释执行 vs 机器码&quot;的差距。</p>
<h2 id="实测结果">实测结果</h2>
<table>
<thead>
<tr>
<th>形态</th>
<th>执行方式</th>
<th>载荷大小</th>
<th>1000 位 π 耗时</th>
<th>相对原生</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>原生动态模块</strong></td>
<td>Xtensa 机器码</td>
<td>约 2.2 KB</td>
<td><strong>427 ms</strong></td>
<td>1×</td>
</tr>
<tr>
<td><strong>WebAssembly 应用（AOT）</strong></td>
<td>Xtensa 机器码（AOT 编译）</td>
<td>约 14 KB</td>
<td><strong>673 ms</strong></td>
<td><strong>1.58×</strong></td>
</tr>
<tr>
<td><strong>WebAssembly 应用（解释）</strong></td>
<td>WAMR 解释器跑字节码</td>
<td>约 14 KB</td>
<td>4863 ms</td>
<td><strong>11.4×</strong></td>
</tr>
<tr>
<td><strong>Lua 脚本（朴素写法）</strong></td>
<td>Lua 解释器跑源码</td>
<td>约 2 KB</td>
<td>27283 ms</td>
<td><strong>63.9×</strong></td>
</tr>
<tr>
<td><strong>Lua 脚本（整数优化写法）</strong></td>
<td>Lua 解释器跑源码</td>
<td>约 2 KB</td>
<td>15703 ms</td>
<td><strong>36.8×</strong></td>
</tr>
<tr>
<td><strong>MicroPython 脚本</strong></td>
<td>官方MicroPython 解释器跑源码</td>
<td>约 2 KB</td>
<td>28247 ms</td>
<td><strong>66.2×</strong></td>
</tr>
</tbody>
</table>
<p>结果不意外：解释执行比原生慢一到两个数量级。</p>
<p><strong>版本与配置</strong>：</p>
<table>
<thead>
<tr>
<th>运行时</th>
<th>版本</th>
<th>配置</th>
</tr>
</thead>
<tbody>
<tr>
<td>MicroPython</td>
<td>v1.29.0</td>
<td>官方固件，Octal-SPIRAM 板</td>
</tr>
<tr>
<td>Lua</td>
<td>5.5</td>
<td>设备侧 <code>LUA_32BITS=1</code></td>
</tr>
<tr>
<td>WAMR</td>
<td>v2.4.0</td>
<td>fast-interp / AOT（PC 侧 Xtensa-LLVM 工具链 + 设备端 AOT 运行时）</td>
</tr>
</tbody>
</table>
<p>均跑在同一块 ESP32-S3 @ 240 MHz。五个实现为同一份 spigot 算法的直译（MicroPython 和 Lua 整数优化版同样用了整数写法 <code>//</code> 与列表预分配），输出逐位一致。</p>
<h2 id="为什么差这么多">为什么差这么多</h2>
<h3 id="1-原生机器码直接跑1">1. 原生：机器码直接跑（1×）</h3>
<p>编译期就把算法翻译成 Xtensa 指令，运行时 CPU 直接执行，没有中间层。寄存器和内存访问都是最优的，427 ms 是这台芯片在 <code>-O2</code> 下的&quot;物理上限&quot;。</p>
<h3 id="2-webassembly字节码--解释器114">2. WebAssembly：字节码 + 解释器（11.4×）</h3>
<p>wasm 应用先被编译成<strong>静态类型的字节码</strong>，运行时由 WAMR（WebAssembly Micro Runtime）逐条解释执行：</p>
<ul>
<li>类型在编译期就定死了（<code>i32</code> 就是 <code>i32</code>），解释器不需要做动态类型判断，可以生成相对紧凑的解释循环（fast-interp）；</li>
<li>但仍要：取指令 → 查操作码分派 → 按语义执行 → 更新程序计数器，每条指令都有固定开销；</li>
<li>数组是一块连续线性内存，下标访问接近原生（这是 wasm 能&quot;只慢 11 倍&quot;而不是更慢的关键）。</li>
</ul>
<h3 id="3-lua源码--动态表639">3. Lua：源码 + 动态表（63.9×）</h3>
<p>Lua 解释器直接读源码逐条执行，负载比较重：</p>
<ul>
<li>每次 <code>a[i]</code> 都要查表：<code>a</code> 是 table（哈希表 / 数组混合结构），下标访问要走一遍结构判断与可能的重哈希；</li>
<li><strong>每个数字都是对象</strong>：<code>10 * a[i] + q * i</code> 里的每个中间量都要新建/回收 number 对象（即便走整型路径也有装箱开销）；</li>
<li>解释循环本身比 wasm 的解释器更厚：操作数要逐字段解析，函数调用要过调用栈与闭包检查。</li>
</ul>
<p>三重叠加，于是 Lua 是 wasm 的 3.2 倍慢，是原生的 37（整数优化写法）~64 倍（朴素写法）。</p>
<h3 id="4-micropython全对象--分代-gc662">4. MicroPython：全对象 + 分代 GC（66.2×）</h3>
<p>MicroPython 与 Lua 同为&quot;源码级解释 + 动态类型&quot;，但对象模型更重：</p>
<ul>
<li><strong>一切都是对象</strong>：整数、列表元素都是堆上的 <code>mp_obj_t</code>，每次算术都要经过对象头 + 类型分派（<code>mp_binary_op</code>），没有 Lua 那种&quot;标签值 + 寄存器 VM&quot;的轻量整数路径；</li>
<li>列表下标访问是完整方法调用链：<code>a[i-1]</code> 要过 <code>mp_obj_subscr</code> → 列表类型分派 → 索引检查，比 Lua 的 <code>luaV_fastgeti</code> 宏展开重得多；</li>
<li><strong>GC 压力</strong>：<code>[2] * LEN</code> 和 <code>res.append()</code> 产生大量堆对象，分代 GC 周期性回收，纯计算循环也躲不开。</li>
</ul>
<p>于是 MicroPython 比优化后的 Lua 还慢 <strong>1.8 倍</strong>，与朴素写法的 Lua 基本打平。</p>
<blockquote>
<p>白话解释：原生是&quot;把答案写死在芯片里&quot;，wasm 是&quot;边翻字典边念&quot;，Lua 是&quot;一边查字典一边还要确认每个字的意思&quot;，MicroPython 是&quot;每个字都要拆开看是哪国语言再翻译&quot;。</p>
</blockquote>
<h2 id="那么aot-值得做吗">那么，AOT 值得做吗？</h2>
<ul>
<li>AOT 把解释器的 4863 ms 压到 <strong>673 ms（1.58×）</strong>，比原先估的&quot;顶多压到 1 秒出头&quot;还好，纯计算场景已接近原生；</li>
<li>但 wasm 应用里真正花时间的往往不是模块内计算，而是<strong>宿主桥调用</strong>（<code>bs_log</code>、共享内存、文件 IO），这些跨边界调用 AOT 一点都加速不了；</li>
<li>代价是工具链：需要 PC 侧 Xtensa-LLVM 交叉编译链 + 设备端 AOT 运行时（官方 LLVM 没有该后端），这是一条长期维护线。</li>
</ul>
<p>结论：性能热区直接写原生 <code>.so</code>。wasm 的取舍点在于沙箱 / 第三方维护 / 生态复用，而不是性能。</p>
<h2 id="选型原则一句话版">选型原则（一句话版）</h2>
<table>
<thead>
<tr>
<th>需求</th>
<th>选谁</th>
</tr>
</thead>
<tbody>
<tr>
<td>每周期执行的算法 / 协议解析 / 编解码</td>
<td><strong>原生动态模块</strong>（10~60 倍差距不是优化能补的）</td>
</tr>
<tr>
<td>沙箱隔离 / 第三方维护 / 复用 wasm 生态</td>
<td>WebAssembly（解释 ~11 倍，AOT 后可到 ~1.6 倍）</td>
</tr>
<tr>
<td>热更新脚本 / 胶水逻辑 / 低频控制</td>
<td>Lua 或 MicroPython（接受 ~40~70 倍代价）</td>
</tr>
</tbody>
</table>
<h2 id="附录参考实现与复现方法">附录：参考实现与复现方法</h2>
<blockquote>
<p>为便于读者复现，这里贴出算法核心（<code>pi_digits</code> / <code>pi_spigot</code>），各语言代码都是设备上实际运行的<strong>完整</strong>实现。</p>
<p>文中出现的 <code>bs_*</code>、<code>esp_timer_get_time()</code>、<code>sys.millis()</code>、<code>time.ticks_ms()</code> 都是设备侧的
<strong>宿主接口</strong>（日志 / 计时 / 输出），换成你平台上的等价物即可；<code>malloc</code>/<code>free</code> 在
wasm 版里接的是宿主堆，桌面运行时（如 wasmtime）下可直接用标准分配器。</p>
</blockquote>
<h3 id="复现方法">复现方法</h3>
<ul>
<li>四份实现均为 Rabinowitz-Wagon spigot 的直译，唯一差异是语言语法，无任何算法级改动；</li>
<li>计时只包裹主循环，排除字符串拼接与日志；</li>
<li>结果用权威 π 前 100 位核对一致后，再对比四位输出全等。</li>
</ul>
<h3 id="附录-a原生-c-实现">附录 A：原生 C 实现</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/*
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 原生 C 模块计算 1000 位圆周率（Rabinowitz-Wagon spigot 算法）
</span></span></span><span class="line"><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="cl"><span class="cm"> * 计时用 esp_timer_get_time()（微秒），仅包裹纯计算主循环。
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdint.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdlib.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;esp_log.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;esp_timer.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">TAG</span> <span class="o">=</span> <span class="s">&#34;pi1000_c&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/* Rabinowitz-Wagon spigot：逐位生成 pi 的数字（res[0] = 整数位 3） */</span>
</span></span><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">uint32_t</span> <span class="nf">pi_digits</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">n</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">res</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">len</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="o">*</span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="n">len</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint32_t</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">a</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">uint32_t</span> <span class="n">q</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kt">uint32_t</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">i</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="kt">uint32_t</span> <span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">a</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span> <span class="o">%</span> <span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">q</span> <span class="o">=</span> <span class="n">x</span> <span class="o">/</span> <span class="n">d</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">q</span> <span class="o">=</span> <span class="n">q</span> <span class="o">/</span> <span class="mi">10</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">q</span> <span class="o">==</span> <span class="mi">9</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">q</span> <span class="o">==</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span><span class="p">)(</span><span class="n">predigit</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nines</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">j</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">predigit</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="n">q</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">nines</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">nines</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                    <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span><span class="p">)</span><span class="n">predigit</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nf">free</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">r</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nf">__attribute__</span><span class="p">((</span><span class="nf">visibility</span><span class="p">(</span><span class="s">&#34;default&#34;</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">app_main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">DIGITS</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* 多算 3 个，截断取前 1000 位 */</span>
</span></span><span class="line"><span class="cl">    <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">N</span> <span class="o">=</span> <span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">3</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">digits</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">((</span><span class="n">N</span> <span class="o">+</span> <span class="mi">8</span><span class="p">)</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">uint8_t</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kt">int64_t</span> <span class="n">t0</span> <span class="o">=</span> <span class="nf">esp_timer_get_time</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="kt">uint32_t</span> <span class="n">nd</span> <span class="o">=</span> <span class="nf">pi_digits</span><span class="p">(</span><span class="n">N</span><span class="p">,</span> <span class="n">digits</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kt">int64_t</span> <span class="n">dt</span> <span class="o">=</span> <span class="nf">esp_timer_get_time</span><span class="p">()</span> <span class="o">-</span> <span class="n">t0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">digits</span> <span class="o">||</span> <span class="n">nd</span> <span class="o">&lt;</span> <span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">ESP_LOGE</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;pi1000_c: failed (nd=%u)&#34;</span><span class="p">,</span> <span class="n">nd</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">free</span><span class="p">(</span><span class="n">digits</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="cm">/* 拼接：整数位 3 + 1000 位小数（digits[0] = 3） */</span>
</span></span><span class="line"><span class="cl">    <span class="kt">char</span> <span class="o">*</span><span class="n">pi</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="nf">malloc</span><span class="p">(</span><span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">8</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">pi</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kt">int</span> <span class="n">o</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">pi</span><span class="p">[</span><span class="n">o</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;3&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">pi</span><span class="p">[</span><span class="n">o</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;.&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">DIGITS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">pi</span><span class="p">[</span><span class="n">o</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span><span class="p">)(</span><span class="sc">&#39;0&#39;</span> <span class="o">+</span> <span class="n">digits</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">        <span class="n">pi</span><span class="p">[</span><span class="n">o</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;\0&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;%s&#34;</span><span class="p">,</span> <span class="n">pi</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nf">free</span><span class="p">(</span><span class="n">pi</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;pi1000_c: %u digits in %lld ms&#34;</span><span class="p">,</span> <span class="n">DIGITS</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)(</span><span class="n">dt</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nf">ESP_LOGI</span><span class="p">(</span><span class="n">TAG</span><span class="p">,</span> <span class="s">&#34;pi1000_c: done&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nf">free</span><span class="p">(</span><span class="n">digits</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="附录-bwebassemblyrust实现">附录 B：WebAssembly（Rust）实现</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="cl"><span class="sd">//! wasm 应用计算 1000 位圆周率（Rabinowitz-Wagon spigot 算法）
</span></span></span><span class="line"><span class="cl"><span class="sd">//!
</span></span></span><span class="line"><span class="cl"><span class="sd">//! 计时用宿主提供的 bs_uptime（微秒），仅包裹纯计算主循环。
</span></span></span><span class="line"><span class="cl"><span class="sd"></span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cp">#![no_std]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cp">#![no_main]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">alloc</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">alloc</span>::<span class="p">{</span><span class="n">format</span><span class="p">,</span><span class="w"> </span><span class="n">string</span>::<span class="nb">String</span><span class="p">,</span><span class="w"> </span><span class="n">vec</span><span class="p">,</span><span class="w"> </span><span class="n">vec</span>::<span class="nb">Vec</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">use</span><span class="w"> </span><span class="n">core</span>::<span class="n">panic</span>::<span class="n">PanicInfo</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cm">/* ---------------- 宿主 import（env 模块） ---------------- */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">extern</span><span class="w"> </span><span class="s">&#34;C&#34;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_log</span><span class="p">(</span><span class="n">json</span>: <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">i32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_result_len</span><span class="p">(</span><span class="n">id</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">i32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_result_copy</span><span class="p">(</span><span class="n">id</span>: <span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">out</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">i32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_result_free</span><span class="p">(</span><span class="n">id</span>: <span class="kt">i32</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_delay_ms</span><span class="p">(</span><span class="n">ms</span>: <span class="kt">i32</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_should_stop</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">i32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">bs_uptime</span><span class="p">(</span><span class="n">j</span>: <span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">l</span>: <span class="kt">i32</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kt">i32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">malloc</span><span class="p">(</span><span class="n">size</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">u8</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">fn</span> <span class="nf">free</span><span class="p">(</span><span class="n">p</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cm">/* ---------------- 分配器：接宿主堆 ---------------- */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">struct</span> <span class="nc">HostAlloc</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">unsafe</span><span class="w"> </span><span class="k">impl</span><span class="w"> </span><span class="n">core</span>::<span class="n">alloc</span>::<span class="n">GlobalAlloc</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">HostAlloc</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">layout</span>: <span class="nc">core</span>::<span class="n">alloc</span>::<span class="n">Layout</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">u8</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">malloc</span><span class="p">(</span><span class="n">layout</span><span class="p">.</span><span class="n">size</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">dealloc</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">ptr</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">_</span>: <span class="nc">core</span>::<span class="n">alloc</span>::<span class="n">Layout</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">free</span><span class="p">(</span><span class="n">ptr</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cp">#[global_allocator]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">static</span><span class="w"> </span><span class="no">HOST_ALLOC</span>: <span class="nc">HostAlloc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HostAlloc</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cm">/* ---------------- 工具 ---------------- */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">log_msg</span><span class="p">(</span><span class="n">msg</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">esc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="n">msg</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">8</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">msg</span><span class="p">.</span><span class="n">chars</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">&#39;&#34;&#39;</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">&#39;\\&#39;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">esc</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="sc">&#39;\\&#39;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">esc</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">json</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;</span><span class="se">{{\&#34;</span><span class="s">level</span><span class="se">\&#34;</span><span class="s">:</span><span class="se">\&#34;</span><span class="s">i</span><span class="se">\&#34;</span><span class="s">,</span><span class="se">\&#34;</span><span class="s">tag</span><span class="se">\&#34;</span><span class="s">:</span><span class="se">\&#34;</span><span class="s">pi1000_rust</span><span class="se">\&#34;</span><span class="s">,</span><span class="se">\&#34;</span><span class="s">msg</span><span class="se">\&#34;</span><span class="s">:</span><span class="se">\&#34;</span><span class="si">{}</span><span class="se">\&#34;}}</span><span class="s">&#34;</span><span class="p">,</span><span class="w"> </span><span class="n">esc</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bs_log</span><span class="p">(</span><span class="n">json</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span><span class="w"> </span><span class="n">json</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">i32</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">bs_result_free</span><span class="p">(</span><span class="n">id</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="sd">/// 调 bs_uptime 返回开机微秒数（解析 {&#34;ok&#34;:true,&#34;us&#34;:N}）。
</span></span></span><span class="line"><span class="cl"><span class="sd"></span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">uptime_us</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">u64</span> <span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bs_uptime</span><span class="p">(</span><span class="sa">b</span><span class="s">&#34;{}&#34;</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">bs_result_len</span><span class="p">(</span><span class="n">id</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="n">n</span><span class="p">.</span><span class="n">max</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">bs_result_copy</span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">buf</span><span class="p">.</span><span class="n">as_mut_ptr</span><span class="p">(),</span><span class="w"> </span><span class="n">n</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">bs_result_free</span><span class="p">(</span><span class="n">id</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">core</span>::<span class="kt">str</span>::<span class="n">from_utf8</span><span class="p">(</span><span class="o">&amp;</span><span class="n">buf</span><span class="p">).</span><span class="n">unwrap_or</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#34;</span><span class="se">\&#34;</span><span class="s">us</span><span class="se">\&#34;</span><span class="s">:&#34;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">rest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="o">..</span><span class="p">];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">digits</span>: <span class="nb">String</span> <span class="o">=</span><span class="w"> </span><span class="n">rest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="n">chars</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="n">take_while</span><span class="p">(</span><span class="o">|</span><span class="n">c</span><span class="o">|</span><span class="w"> </span><span class="n">c</span><span class="p">.</span><span class="n">is_ascii_digit</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">.</span><span class="n">collect</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">digits</span><span class="p">.</span><span class="n">parse</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">v</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="mi">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cm">/* ---------------- spigot 算法 ---------------- */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="sd">/// 生成 pi 的数字序列（res[0] = 整数位 3，res[1..] = 小数位）。
</span></span></span><span class="line"><span class="cl"><span class="sd"></span><span class="k">fn</span> <span class="nf">pi_digits</span><span class="p">(</span><span class="n">n</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Vec</span><span class="o">&lt;</span><span class="kt">u8</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="mi">2</span><span class="k">u32</span><span class="p">;</span><span class="w"> </span><span class="n">len</span><span class="p">];</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">nines</span>: <span class="kt">u32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">predigit</span>: <span class="kt">u32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Vec</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="n">n</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">..=</span><span class="n">n</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">q</span>: <span class="kt">u32</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">len</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u32</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">d</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">q</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">d</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">i</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">q</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">9</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">nines</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">res</span><span class="p">.</span><span class="n">push</span><span class="p">((</span><span class="n">predigit</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">nines</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">res</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">predigit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">nines</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">res</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">predigit</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">predigit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">q</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">nines</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">nines</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">res</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="mi">9</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">nines</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">res</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">predigit</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">res</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cm">/* ---------------- main ---------------- */</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cp">#[no_mangle]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">pub</span><span class="w"> </span><span class="k">extern</span><span class="w"> </span><span class="s">&#34;C&#34;</span><span class="w"> </span><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="kt">i32</span> <span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="no">DIGITS</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">1000</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">t0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">uptime_us</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">digits</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pi_digits</span><span class="p">(</span><span class="no">DIGITS</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">3</span><span class="p">);</span><span class="w"> </span><span class="c1">// 多算几个，截断取前 1000 位
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">dt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">uptime_us</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">t0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="c1">// 拼接：整数位 3 + 1000 位小数（digits[0] = 3）
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">pi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="no">DIGITS</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">2</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">pi</span><span class="p">.</span><span class="n">push_str</span><span class="p">(</span><span class="s">&#34;3.&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">..=</span><span class="no">DIGITS</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">pi</span><span class="p">.</span><span class="n">push</span><span class="p">((</span><span class="sa">b</span><span class="sc">&#39;0&#39;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">digits</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">char</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">log_msg</span><span class="p">(</span><span class="o">&amp;</span><span class="n">pi</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">log_msg</span><span class="p">(</span><span class="o">&amp;</span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;pi1000_rust: </span><span class="si">{}</span><span class="s"> digits in </span><span class="si">{}</span><span class="s"> ms&#34;</span><span class="p">,</span><span class="w"> </span><span class="no">DIGITS</span><span class="p">,</span><span class="w"> </span><span class="n">dt</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">1000</span><span class="p">));</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">log_msg</span><span class="p">(</span><span class="s">&#34;pi1000_rust: done&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="mi">0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="cp">#[panic_handler]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">fn</span> <span class="nf">panic</span><span class="p">(</span><span class="n">_</span>: <span class="kp">&amp;</span><span class="nc">PanicInfo</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="o">!</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">core</span>::<span class="n">arch</span>::<span class="n">wasm32</span>::<span class="n">unreachable</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="附录-clua-的朴素实现使用mathfloor算除法">附录 C：Lua 的朴素实现，使用math.floor算除法</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="c1">-- 计算 1000 位圆周率（Rabinowitz-Wagon spigot 算法）</span>
</span></span><span class="line"><span class="cl"><span class="c1">-- 参考 Simeon Simeonov 的 Pascal 原版（pi_spigot），本机已与权威前 100 位核对。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">sys</span> <span class="o">=</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;sys&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">DIGITS</span> <span class="o">=</span> <span class="mi">1000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- Rabinowitz-Wagon spigot：逐位生成 pi 的数字（含整数位 3 在最前）。</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="kr">function</span> <span class="nf">pi_spigot</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">len</span> <span class="o">=</span> <span class="n">math.floor</span><span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">len</span> <span class="kr">do</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">nines</span><span class="p">,</span> <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">res</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="kr">for</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">        <span class="kd">local</span> <span class="n">q</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="n">len</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">            <span class="kd">local</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">i</span>
</span></span><span class="line"><span class="cl">            <span class="kd">local</span> <span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span> <span class="o">%</span> <span class="n">d</span>
</span></span><span class="line"><span class="cl">            <span class="n">q</span> <span class="o">=</span> <span class="n">math.floor</span><span class="p">(</span><span class="n">x</span> <span class="o">/</span> <span class="n">d</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="kr">end</span>
</span></span><span class="line"><span class="cl">        <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">        <span class="n">q</span> <span class="o">=</span> <span class="n">math.floor</span><span class="p">(</span><span class="n">q</span> <span class="o">/</span> <span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="kr">if</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">9</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span> <span class="o">=</span> <span class="n">nines</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">        <span class="kr">elseif</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">10</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span><span class="p">[</span><span class="o">#</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="kr">for</span> <span class="n">_</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nines</span> <span class="kr">do</span> <span class="n">res</span><span class="p">[</span><span class="o">#</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span><span class="p">,</span> <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="kr">else</span>
</span></span><span class="line"><span class="cl">            <span class="kr">if</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="kr">then</span> <span class="n">res</span><span class="p">[</span><span class="o">#</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="n">q</span>
</span></span><span class="line"><span class="cl">            <span class="kr">if</span> <span class="n">nines</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">                <span class="kr">for</span> <span class="n">_</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nines</span> <span class="kr">do</span> <span class="n">res</span><span class="p">[</span><span class="o">#</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">9</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">                <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">            <span class="kr">end</span>
</span></span><span class="line"><span class="cl">        <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span><span class="p">[</span><span class="o">#</span><span class="n">res</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span>
</span></span><span class="line"><span class="cl">    <span class="kr">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- 计算 + 计时（多算几个，截断取前 DIGITS 位，避免 9 传播导致少位）</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">t0</span> <span class="o">=</span> <span class="n">sys.millis</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">digits</span> <span class="o">=</span> <span class="n">pi_spigot</span><span class="p">(</span><span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">sys.millis</span><span class="p">()</span> <span class="o">-</span> <span class="n">t0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- 拼接输出：整数位 3 + DIGITS 位小数（res[1] = 整数位 3）</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">pi</span> <span class="o">=</span> <span class="s2">&#34;3.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">1</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">pi</span> <span class="o">=</span> <span class="n">pi</span> <span class="o">..</span> <span class="n">tostring</span><span class="p">(</span><span class="n">digits</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: &#34;</span> <span class="o">..</span> <span class="n">pi</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="n">string.format</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: %d digits in %d ms&#34;</span><span class="p">,</span> <span class="n">DIGITS</span><span class="p">,</span> <span class="n">dt</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: done&#34;</span><span class="p">)</span>
</span></span></code></pre></div><h3 id="附录-dlua-的优化实现使用算整数除法">附录 D：Lua 的优化实现，使用//算整数除法</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="c1">-- 计算 1000 位圆周率（Rabinowitz-Wagon spigot 算法）</span>
</span></span><span class="line"><span class="cl"><span class="c1">-- 参考 Simeon Simeonov 的 Pascal 原版（pi_spigot），本机已与权威前 100 位核对。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">sys</span> <span class="o">=</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;sys&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">DIGITS</span> <span class="o">=</span> <span class="mi">1000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- Rabinowitz-Wagon spigot：逐位生成 pi 的数字（含整数位 3 在最前）。</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="kr">function</span> <span class="nf">pi_spigot</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">len</span> <span class="o">=</span> <span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="mi">3</span>          <span class="c1">-- 整数整除（不超 int32）</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">a</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">len</span> <span class="kr">do</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">2</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">nines</span><span class="p">,</span> <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">res</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="cl">    <span class="kd">local</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span>                         <span class="c1">-- 本地计数器替代 #res + 1</span>
</span></span><span class="line"><span class="cl">    <span class="kr">for</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">        <span class="kd">local</span> <span class="n">q</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="n">len</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">            <span class="kd">local</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">i</span> <span class="c1">-- 全整数，int32 内安全</span>
</span></span><span class="line"><span class="cl">            <span class="kd">local</span> <span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span> <span class="o">%</span> <span class="n">d</span>                <span class="c1">-- 整数取模</span>
</span></span><span class="line"><span class="cl">            <span class="n">q</span> <span class="o">=</span> <span class="n">x</span> <span class="o">//</span> <span class="n">d</span>                  <span class="c1">-- 整数整除（OP_IDIV）</span>
</span></span><span class="line"><span class="cl">        <span class="kr">end</span>
</span></span><span class="line"><span class="cl">        <span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">        <span class="n">q</span> <span class="o">=</span> <span class="n">q</span> <span class="o">//</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">        <span class="kr">if</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">9</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span> <span class="o">=</span> <span class="n">nines</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">        <span class="kr">elseif</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">10</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="kr">for</span> <span class="n">_</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nines</span> <span class="kr">do</span> <span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span><span class="p">,</span> <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="kr">else</span>
</span></span><span class="line"><span class="cl">            <span class="kr">if</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="kr">then</span> <span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="n">q</span>
</span></span><span class="line"><span class="cl">            <span class="kr">if</span> <span class="n">nines</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="kr">then</span>
</span></span><span class="line"><span class="cl">                <span class="kr">for</span> <span class="n">_</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nines</span> <span class="kr">do</span> <span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="mi">9</span> <span class="kr">end</span>
</span></span><span class="line"><span class="cl">                <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">            <span class="kr">end</span>
</span></span><span class="line"><span class="cl">        <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="kr">end</span>
</span></span><span class="line"><span class="cl">    <span class="n">r</span> <span class="o">=</span> <span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">res</span><span class="p">[</span><span class="n">r</span><span class="p">]</span> <span class="o">=</span> <span class="n">predigit</span>
</span></span><span class="line"><span class="cl">    <span class="kr">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- 计算 + 计时（多算几个，截断取前 DIGITS 位，避免 9 传播导致少位）</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">t0</span> <span class="o">=</span> <span class="n">sys.millis</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">digits</span> <span class="o">=</span> <span class="n">pi_spigot</span><span class="p">(</span><span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">dt</span> <span class="o">=</span> <span class="n">sys.millis</span><span class="p">()</span> <span class="o">-</span> <span class="n">t0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">-- 拼接输出：整数位 3 + DIGITS 位小数（res[1] = 整数位 3）</span>
</span></span><span class="line"><span class="cl"><span class="kd">local</span> <span class="n">pi</span> <span class="o">=</span> <span class="s2">&#34;3.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="kr">for</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">1</span> <span class="kr">do</span>
</span></span><span class="line"><span class="cl">    <span class="n">pi</span> <span class="o">=</span> <span class="n">pi</span> <span class="o">..</span> <span class="n">tostring</span><span class="p">(</span><span class="n">digits</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="kr">end</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: &#34;</span> <span class="o">..</span> <span class="n">pi</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="n">string.format</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: %d digits in %d ms&#34;</span><span class="p">,</span> <span class="n">DIGITS</span><span class="p">,</span> <span class="n">dt</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">print</span><span class="p">(</span><span class="s2">&#34;pi1000_lua: done&#34;</span><span class="p">)</span>
</span></span></code></pre></div><h3 id="附录-emicropython-实现">附录 E：MicroPython 实现</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># MicroPython 计算 1000 位圆周率（Rabinowitz-Wagon spigot 算法）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 计时用 time.ticks_ms()，仅包裹纯计算主循环。</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span> <span class="k">as</span> <span class="nn">_t</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">DIGITS</span> <span class="o">=</span> <span class="mi">1000</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">pi_spigot</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">LEN</span> <span class="o">=</span> <span class="p">(</span><span class="mi">10</span> <span class="o">*</span> <span class="n">n</span><span class="p">)</span> <span class="o">//</span> <span class="mi">3</span>          <span class="c1"># 整数整除</span>
</span></span><span class="line"><span class="cl">    <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="n">LEN</span>                <span class="c1"># 预分配列表</span>
</span></span><span class="line"><span class="cl">    <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">q</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">LEN</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">            <span class="n">x</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">*</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">q</span> <span class="o">*</span> <span class="n">i</span>
</span></span><span class="line"><span class="cl">            <span class="n">d</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">            <span class="n">a</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span> <span class="o">%</span> <span class="n">d</span>
</span></span><span class="line"><span class="cl">            <span class="n">q</span> <span class="o">=</span> <span class="n">x</span> <span class="o">//</span> <span class="n">d</span>
</span></span><span class="line"><span class="cl">        <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">q</span> <span class="o">%</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">        <span class="n">q</span> <span class="o">=</span> <span class="n">q</span> <span class="o">//</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">9</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="cl">        <span class="k">elif</span> <span class="n">q</span> <span class="o">==</span> <span class="mi">10</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">predigit</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">res</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">nines</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">            <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">j</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">predigit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">predigit</span> <span class="o">=</span> <span class="n">q</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">nines</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="n">res</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="mi">9</span><span class="p">]</span> <span class="o">*</span> <span class="n">nines</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="n">nines</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="cl">    <span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">predigit</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">res</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">t0</span> <span class="o">=</span> <span class="n">_t</span><span class="o">.</span><span class="n">ticks_ms</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">digits</span> <span class="o">=</span> <span class="n">pi_spigot</span><span class="p">(</span><span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">3</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">dt</span> <span class="o">=</span> <span class="n">_t</span><span class="o">.</span><span class="n">ticks_diff</span><span class="p">(</span><span class="n">_t</span><span class="o">.</span><span class="n">ticks_ms</span><span class="p">(),</span> <span class="n">t0</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">pi</span> <span class="o">=</span> <span class="s2">&#34;3.&#34;</span> <span class="o">+</span> <span class="s2">&#34;&#34;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">digits</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="n">DIGITS</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;pi1000_py: &#34;</span> <span class="o">+</span> <span class="n">pi</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;pi1000_py: </span><span class="si">%d</span><span class="s2"> digits in </span><span class="si">%d</span><span class="s2"> ms&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">DIGITS</span><span class="p">,</span> <span class="n">dt</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;pi1000_py: done&#34;</span><span class="p">)</span>
</span></span></code></pre></div><hr>
<p><em>本文数据来自一次真实设备实测。算法为公开的经典 spigot 算法，可按任意语言复现。</em></p>
<p><strong>📚 相关阅读</strong></p>
<ul>
<li><a href="https://tech-snippets.xyz/posts/elf-loader-base-architecture-vs-esp-brookesia-2026/">动态扩展运行时架构研究：elf_loader 基座架构与 ESP-Brookesia 对比</a> —— 四种执行方式背后的架构设计：elf_loader 单一基座 vs Brookesia 多后端，以及本文实测数据对应的选型结论</li>
</ul>
]]></content:encoded></item></channel></rss>