<?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/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>WebAssembly on 弦而時習之</title><link>https://blog.aotoki.me/tags/WebAssembly/</link><description>Recent content in WebAssembly on 弦而時習之</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><managingEditor>contact@aotoki.me (蒼時弦也)</managingEditor><webMaster>contact@aotoki.me (蒼時弦也)</webMaster><lastBuildDate>Mon, 15 Jun 2026 21:40:29 +0800</lastBuildDate><atom:link href="https://blog.aotoki.me/tags/WebAssembly/index.xml" rel="self" type="application/rss+xml"/><item><title>Kobako：Cold Start 原來能快 100 倍？</title><link>https://blog.aotoki.me/posts/2026/06/17/kobako-cold-start-100x-faster/</link><category>LLM</category><category>AI</category><category>經驗</category><category>Ruby</category><category>WebAssembly</category><category>Gem</category><category>效能</category><pubDate>Wed, 17 Jun 2026 00:00:00 +0800</pubDate><author>contact@aotoki.me (蒼時弦也)</author><guid>https://blog.aotoki.me/posts/2026/06/17/kobako-cold-start-100x-faster/</guid><description>&lt;p&gt;&lt;a href="https://github.com/elct9620/kobako"&gt;Kobako&lt;/a&gt; 是近期我針對 Ruby 生態系中，對 &lt;a href="https://blog.aotoki.me/tags/Harness-Engineering/"&gt;Harness Engineering&lt;/a&gt; 支援所開發基於 WebAssembly 和 mruby 的沙盒（Sandbox）用來填補 AI 所撰寫的程式碼，沒有可以安全運行的環境。&lt;/p&gt;
&lt;p&gt;關於 Kobako 的設計理念，我在 &lt;a href="https://blog.aotoki.me/posts/2026/05/20/kobako-ruby-sandbox-for-ai/"&gt;上一篇文章&lt;/a&gt; 已經介紹過，這次想聊的是效能。在初期的版本中 Cold Start（冷啟動，通常指初次啟動）大概要花上 500 ms 左右，這遠比最佳實踐通常會抓 200 ms 回應來說慢的不少，即使 AI 通常接受更慢的回應，但這不是等待 LLM 回應，仍該用過去的 API 標準來看待。&lt;/p&gt;</description><content:encoded>&lt;p&gt;&lt;a href="https://github.com/elct9620/kobako"&gt;Kobako&lt;/a&gt; 是近期我針對 Ruby 生態系中，對 &lt;a href="https://blog.aotoki.me/tags/Harness-Engineering/"&gt;Harness Engineering&lt;/a&gt; 支援所開發基於 WebAssembly 和 mruby 的沙盒（Sandbox）用來填補 AI 所撰寫的程式碼，沒有可以安全運行的環境。&lt;/p&gt;
&lt;p&gt;關於 Kobako 的設計理念，我在 &lt;a href="https://blog.aotoki.me/posts/2026/05/20/kobako-ruby-sandbox-for-ai/"&gt;上一篇文章&lt;/a&gt; 已經介紹過，這次想聊的是效能。在初期的版本中 Cold Start（冷啟動，通常指初次啟動）大概要花上 500 ms 左右，這遠比最佳實踐通常會抓 200 ms 回應來說慢的不少，即使 AI 通常接受更慢的回應，但這不是等待 LLM 回應，仍該用過去的 API 標準來看待。&lt;/p&gt;
&lt;h2 id="pre-compile"&gt;預先編譯&lt;/h2&gt;
&lt;p&gt;WebAssembly 經過多年發展後，已經有很多新的技術跟規格，其中 &lt;code&gt;cwasm&lt;/code&gt;（Wasmtime 把 &lt;code&gt;.wasm&lt;/code&gt; 預先編譯後的產物）就是一種 AOT（Ahead-of-Time，預先編譯）的處理方式。&lt;/p&gt;
&lt;p&gt;原因在於，我們編譯為 &lt;code&gt;wasm&lt;/code&gt; 格式後，是針對 WebAssembly 的虛擬機器所設計，如果拿來跑 mruby 大致上就是在一個 WebAssembly 虛擬機器中，再啟動一個 mruby 虛擬機器，套了兩層在運作。&lt;/p&gt;
&lt;p&gt;透過 &lt;code&gt;cwasm&lt;/code&gt; 處理，會先在運行的環境直接編譯成當下環境 CPU 對應的機器碼，那就無限接近於把 WebAssembly 虛擬機器消除，只留下 mruby 虛擬機器的成本，啟動速度就從 500 ms 縮減到 5 ms 左右，因此 Cold Start 的時間馬上快上 100 倍。&lt;/p&gt;
&lt;p&gt;簡單來說，Kobako 本身並沒有做太多處理，只是很單純的透過 WebAssembly 的標準，就極大的加速到跟一次簡單的 SQL 查詢差不多，對大部分應用幾乎等同無感。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;今年 RubyKaigi 中 Matz 的新專案 &lt;a href="https://github.com/matz/spinel"&gt;Spinel&lt;/a&gt; 正好就是一種 Ruby 的 AOT 編譯器，至於 &lt;code&gt;cwasm&lt;/code&gt; 我則是第一次接觸到，畢竟過往都還停留在 &lt;code&gt;wasm&lt;/code&gt; 的認識，這次跟 AI 協作意外學到新的概念。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="pre-boot"&gt;預先偷跑&lt;/h2&gt;
&lt;p&gt;當在裝置上啟動過一次 Kobako 後，後續的 Cold Start 就會因為 AOT 從 500 ms 變成只要 5 ms 就能啟動完畢，那麼 &lt;code&gt;Kobako::Sandbox.new&lt;/code&gt; 也能變快嗎？&lt;/p&gt;
&lt;p&gt;原本的設計上，我們會把每個 &lt;code&gt;Kobako::Sandbox.new&lt;/code&gt; 都獨立建立一個實例（Instance）並且在每次 &lt;code&gt;#run&lt;/code&gt; 或者 &lt;code&gt;#eval&lt;/code&gt; 時重新初始化 mruby 虛擬機器，確保可重用與乾淨隔離，但每多一個沙盒就會多佔用約 560 KB 的記憶體，對於希望「大量產生、刪除」的設計不太友善，當數量增加記憶體就會急劇消耗，而且還有一個初始化的時間約 130 µs 的成本在，即使這已經非常快。&lt;/p&gt;
&lt;p&gt;Wasmtime 提供了一個叫做 &lt;a href="https://crates.io/crates/wasmtime-wizer"&gt;wizer&lt;/a&gt; 的機制，我們可以預先把運行的記憶體準備好。這是因為每次啟動新的 mruby 虛擬機器時，對所有使用相同 &lt;code&gt;.wasm&lt;/code&gt; 的 &lt;code&gt;Kobako::Sandbox&lt;/code&gt; 是完全相同的記憶體，那麼預先把把 mruby 虛擬機器跑到啟動好的狀態存到 &lt;code&gt;.wasm&lt;/code&gt; 中，未來啟動時就不需要再次去計算。&lt;/p&gt;
&lt;p&gt;接下來搭配 Wasmtime 的 &lt;code&gt;InstancePre&lt;/code&gt; 和 &lt;code&gt;Copy-on-Write&lt;/code&gt; 兩個設計，就可以把啟動時間跟記憶體使用壓的更低。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;InstancePre&lt;/code&gt; - 把 Kobako 的 ABI（Application Binary Interface，應用程式二進位介面）先計算好，未來重新利用，不用每次都計算&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Copy-on-Write&lt;/code&gt; - 建立新的 &lt;code&gt;Kobako::Sandbox&lt;/code&gt; 時，使用同一份 Baked 的 mruby 虛擬機器，不另外建立&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;透過這些處理，做一次 &lt;code&gt;Kobako::Sandbox.new&lt;/code&gt; 的時間，就從 130 µs 降低到 30 µs 左右，記憶體使用從 560 KB 減少到 1 KB，因為不再需要每個沙盒都保存完整的記憶體，在有改變之前都會使用同一份基礎。&lt;/p&gt;
&lt;h2 id="design-decision"&gt;設計取捨&lt;/h2&gt;
&lt;p&gt;原本在我的預期中，會透過消耗相對多的記憶體去換取更快的速度，但結果反而出乎我的預期，在速度跟記憶體使用上都得到很大的提升，更快地幫助我把專案推進到可以正式上線的等級。&lt;/p&gt;
&lt;p&gt;尤其是這次用到的技術，很多都不是新技術，而是建構在已經被使用多年的機制。但透過 AI 的輔助，我很快的挖掘出這些技術，並且放置到恰當的位置。&lt;/p&gt;
&lt;p&gt;這對軟體工程師這個職業的影響，依舊還是對應我們所熟知的衝擊，有經驗的工程師更有價值，原因就是「無條件接受」跟「有意識篩選」是兩件事情，後者是專業工程師的素養，在這次改版之前，我已經直覺的「可以用 Cache 重用」這樣的直覺判斷，先減少「每次都要等 500 ms」變成只等一次。&lt;/p&gt;
&lt;p&gt;然而當整體功能完善後，考慮到每次啟動的時間跟佔用的記憶體，就讓我開始思考「還能更好嗎？」但受限於對 WebAssembly 技術不是熟悉的情境，透過 AI 大量搜集資料、探索，很快就確認 AOT、Bake 等技術是合理且有幫助的，分段處理（如果 AOT 不成立，做 Bake 大概也沒差異太大）一步一步推進來達到更好的成果。&lt;/p&gt;
&lt;p&gt;我認為這在 AI 時代是很值得思考的問題，我們從 AI 身上拿到的「加速」是什麼？以 Kobako 的案例，整個專案極大的提升背後，是快速搜集資料，以及對軟體開發知識的熟悉得出適當的判斷。&lt;/p&gt;</content:encoded></item></channel></rss>