بازنویسی Bun در Rust: ۱۱ روز، ۶,۷۷۸ commit و آنچه واقعاً تغییر کرد
تیم Bun در می ۲۰۲۶ چیزی غیرمعمول منتشر کرد: آنها کل هسته بومی runtime را با یک پورت Rust جایگزین کردند و این کار را در ۱۱ روز انجام دادند.
افشا در بالای اعلامیه لحن را تعیین میکند. Bun در دسامبر ۲۰۲۵ توسط Anthropic خریداری شد. Jarred Sumner، خالق Bun، از یک نسخه پیش از انتشار Claude—یک «مدل سطح Mythos» که آن را Fable 5 مینامند—برای بیشتر کار استفاده کرد. این یک آزمایش فکری نیست. Bun v1.4.0، اولین نسخه Rust، در canary است.
اعداد خام:
- ۵۳۵,۴۹۶ خط Zig (به جز کامنتها) به یک codebase Rust تبدیل شد
- ۶,۷۷۸ commit بین ۳ می و ۱۴ می
- ۱,۴۴۸ فایل
.zigبه طور مکانیکی به.rsپورت شد - ~$۱۶۵,۰۰۰ هزینه API (۵.۹B token ورودی uncached، ۶۹۰M token خروجی)
- اوج: ۶۴ کلود که همزمان در ۴ worktree اجرا میشدند
Bun همیشه یک شرط Zig بود
Bun به عنوان یک پورت خط-به-خط از transpiler JS/TS esbuild از Go به Zig شروع شد. سامنر اولین خط Zig خود را در ۱۶ آوریل ۲۰۲۱ نوشت. نسخه اولیه—transpiler، minifier، bundler، مدیر بسته سازگار با npm، تستران شبیه Jest، سطح API Node.js—توسط یک نفر در یک سال، در یک آپارتمان تنگ اوکلند، قبل از اینکه LLMها برای این نوع کار مفید باشند نوشته شد.
آن شرط جواب داد. Bun CLI حالا بیش از ۲۲ میلیون دانلود ماهانه دارد. Claude Code و OpenCode از آن به عنوان runtime خود استفاده میکنند. Vercel، Railway و DigitalOcean پشتیبانی درجه یک ارائه میدهند.
گستردگی همچنین مشکل بود.
بدهی: حافظه GC در کنار حافظه دستی
JavaScript garbage-collected است. Bun JavaScriptCore را جاسازی میکند به علاوه یک کوه کتابخانه C/C++: uWebSockets، BoringSSL، SQLite، lsquic. Zig، مثل C، حافظه را برای تو مدیریت نمیکند. کار Bun این است که بین یک زبان GC شده و کد بومی مدیریتشده دستی بنشیند و آن مرز جایی است که بیشتر بدترین باگهایش زندگی میکردند.
اعلامیه نمونهای از آنچه در v1.3.14 به تنهایی رفع کردند فهرست میکند: یک heap-use-after-free در node:zlib، use-after-free در node:http2 از callbacks re-entrant، نوشتن خارج از محدوده در UDPSocket.sendMany، نشت حافظه به ازای هر tls.connect، یک double-free در CSS parser. لیست ادامه دارد.
سامنر صریح است که این تقصیر Zig نیست. «اگر Zig نبود اینقدر پیش نمیرفتیم، و همیشه سپاسگزار خواهم بود.» مسئله ساختاری است: مدیریت lifetimes در مرز GC در هر زبانی که برای آن طراحی نشده سخت است، و جواب Zig—defer صریح در هر نقطه فراخوانی—در مسیرهای خطای به ندرت رسیده به راحتی اشتباه میشود.
او C++ را سنجید. حدود ۲۰٪ Bun از قبل C++ است. اما Rust متفاوت است: در Rust ایمن، use-after-free، double-free و «فراموشی آزاد کردن» خطاهای کامپایلر هستند.
استراتژی: transpile، نه بازطراحی
بازنویسیها شهرت بدی دارند، و به دلیلی خوب. یک بازنویسی از ابتدای ۵۳۵ هزار خط، ویژگیها و رفعها را برای یک سال متوقف میکرد. شکل انتخابشده Bun یک پورت مکانیکی بود: همان معماری، همان اهداف عملکرد، همان ویژگیها، همان مجموعه تست—فقط در Rust.
دو تصمیم کل تلاش را هدایت کرد:
۱. یکباره، نه تدریجی. تجربه سامنر در پورت کردن esbuild به Zig به او گفت بازنویسیهای تدریجی داربست موقت باقی میگذارند که بیشتر ضرر دارد تا فایده. ۲. طوری بساز که transpile شده به نظر برسد. هدف Rustای بود که مثل Zigای که از آن آمده خوانده شود، تا بعد از انتشار v1.4 به سمت Rust اصطلاحی بازآرایی شود.
اجرا: ۶۴ کلود، ۱۱ روز
پورت به عنوان حدود ۵۰ «workflow پویا» در Claude Code، به طور مداوم، به مدت ۱۱ روز اجرا شد. هر workflow یک حلقه بود: یک task بگیر، کد تولید کن، بررسی بگیر، بازخورد اعمال کن.
بخش جالب مدل بررسی است. به ازای هر پیادهساز، دو یا بیشتر بررسیکننده adversarial وجود داشت—جلسات جداگانه Claude که به آنها گفته شده بود فرض کنند کد اشتباه است و هر دلیلی که fail میکند را پیدا کنند. پیادهساز هرگز بررسی نمیکند؛ بررسیکننده هرگز پیادهسازی نمیکند.
چند مکانیک ارزش بیرون کشیدن دارند:
- ابتدا آزمایشی. قبل از تعهد به همه ۱,۴۴۸ فایل، ۳ فایل را پورت کردند.
- تقسیم worktree. رفع: ۴ worktree، هرکدام ۱۶ کلود، با قانونی برای اجرا نکردن git یا cargo در وسط task.
- خطاهای کامپایلر به عنوان صف کار.
cargo checkحدود ۱۶,۰۰۰ خطا را در یک فایل ریخت و ۶۴ کلود دست به کار شدند. - وابستگیهای چرخهای. Zig عملاً یک واحد کامپایل بود؛ Rust به حدود ۱۰۰ crate نیاز داشت.
timeline
title بازنویسی ۱۱ روزه Zig → Rust Bun (می ۲۰۲۶)
۲۰۲۶-۰۵-۰۳ : شاخه پورت باز شد
۲۰۲۶-۰۵-۰۶ : ~۱۶,۰۰۰ خطای کامپایلر، ۶۴ کلود
۲۰۲۶-۰۵-۰۸ : اولین اجرای CI (۹۷۲ فایل fail)
۲۰۲۶-۰۵-۰۹ : لینوکس x64 سبز شد
۲۰۲۶-۰۵-۱۱ : ویندوز سبز شد (آخرین پلتفرم)
۲۰۲۶-۰۵-۱۴ : هر ۶ پلتفرم سبز، ادغام شد
Rust واقعاً چه چیزی خرید
باگها. Bun v1.4.0 ۱۲۸ باگ را که در v1.3.14 تکثیر میشوند رفع میکند.
حافظه. Drop جایگزین defer در هر نقطه فراخوانی شد. در v1.3.14 هر build حدود ~۳ مگابایت برای همیشه نشت میکند؛ در v1.4.0 حافظه تثبیت میشود.
| Buildها | v1.3.14 | v1.4.0 |
|---|---|---|
| ۵۰۰ | ۱,۹۱۴ مگابایت | ۵۲۶ مگابایت |
| ۱,۰۰۰ | ۳,۵۰۶ مگابایت | ۵۸۶ مگابایت |
| ۲,۰۰۰ | ۶,۷۴۵ مگابایت | ۶۰۹ مگابایت |
اندازه باینری. بازنویسی Rust به تنهایی ۳.۸ مگابایت (ویندوز)، ۵.۵ مگابایت (مک)، ۶.۸ مگابایت (لینوکس) کم کرد.
سرعت. LTO بینزبانی بین C/C++ و Rust به کامپایلر اجازه میدهد بین مرزهای زبان inline کند. Bun افزایش ۲–۵٪ اندازهگیری کرد.
جایی که پورت لغزید
یک transpile وفادار از ۵۳۵ هزار خط رایگان نیست. ۱۹ پسرفت مستند وجود دارد، همه رفع شدهاند. موارد آموزشی شکافهای معنایی کوچک بین زبانها هستند:
- اثرات جانبی
debug_assert!.assertZig یک تابع است، پس آرگومانش در هر build اجرا میشود.debug_assert!Rust یک ماکرو است که در release پاک میشود—یک فراخوانیinsert_staleکه وضعیت HMR را جهش میداد بیصدا از اجرا ایستاد. - برشهای طول فرد. Helper Zig یک بایت انتهایی فرد را نادیده میگرفت؛
bytemuck::cast_sliceروی آن panic میکند. - بررسیهای مرز.
ReleaseFastZig آنها را حذف میکند؛ Rust نگهشان میدارد.
این چه معنایی دارد
زاویه LLM را کنار بگذارید و یک داستان مهندسی واقعی وجود دارد: پروژهای به سقف آنچه مدیریت دستی حافظه میتوانست در مقیاس به آن بدهد رسید و borrow checker Rust را به عنوان ابزاری برای غیرممکن کردن یک کلاس کامل از باگها به جای صرفاً منصرف کردن انتخاب کرد.
زاویه LLM بخشی است که مردم درباره آن بحث خواهند کرد. سامنر صریح است که این کار سه مهندس با زمینه کامل codebase حدود یک سال طول میکشید و هرگز انجامش نمیدادند—جایگزین واقعگرایانه «هیچ کاری نکن و به رفع باگها ادامه بده» بود. در عوض، یک مهندس که ۶۴ کلود را نظارت میکرد در ۱۱ روز برای ~$۱۶۵K انجامش داد.
خط پایانی او خطی است که به طرز جالبی پیر میشود: «یک مهندس امروز میتواند خیلی بیشتر از یک سال پیش انجام دهد.»