Bun
    Bun
    文件指南部落格文件指南部落格Discord logoGitHub logo

    Bun v0.1.12


    Jarred Sumner · September 18, 2022

    升級方式

    bun upgrade
    

    安裝方式

    curl https://bun.dev.org.tw/install | bash
    

    如果您在升級時遇到任何問題

    bun install 變得更快且更可靠

    先前,在 Linux 上執行 bun install 時,每 80,000 次冷啟動套件安裝中,至少會崩潰或卡住 1 次 🙈。對於下載速度低於 100 mbps 的情況尤其糟糕。有時也存在 DNS 主機名稱解析問題(這會導致另一個崩潰)。如果您使用的 Linux 核心版本早於 v5.5,或者 memlock 限制較低(例如使用 Ubuntu 18.04),則根本無法運作。

    Bun v0.1.12 修復了這個問題。

    為了進行端對端測試,我讓一台電腦在迴圈中冷啟動安裝 512 MB 的 node_modules 兩個小時(至少 800,000 次冷啟動套件安裝),並且每次都成功安裝,沒有崩潰或卡住(與 Bun v0.1.11 和更早版本不同)

    第一次執行安裝了 100 次,第二次執行安裝了 1,000 次。

    image

    四個不同的原因導致了穩定性問題

    • 程式碼中等待非同步工作完成時發生死鎖(提取檔案和解析 JSON 在執行緒池中進行)。這個問題通過以下方式解決:(1)將 HTTP 請求移至多生產者單消費者無鎖佇列,以及(2)使用 eventfd 或 machport 通知就緒狀態,而不是 futex。
    • HTTP 客戶端在暫停/從非同步發生的工作中恢復時存在錯誤。這個問題在重寫 HTTP 客戶端時得到修復(它不再使用 Zig 的 async/await)
    • 讀取空的 JSON 檔案時崩潰。這是一個簡單的修復。
    • 由於任何原因導致 DNS 解析失敗時崩潰。這個問題在重寫 HTTP 客戶端時得到修復,因為現在它使用 libc 的 getaddrinfo

    這些問題中的許多也適用於 macOS(memlock 限制問題除外)

    `bun install` 中仍然缺少重要的功能,包括對 `git` 依賴項、`github` 依賴項、`npm:` 套件別名和工作區支援的支援。這些功能尚未實作,這與現有功能的穩定性問題不同。

    fetch() 變得更快且更可靠

    Bun 的 HTTP 客戶端的事件程式碼已重寫為使用 uSockets,並且與並行任務排程和 HTTP Keep-Alive 的更改一起,使在 Bun 中發送 HTTP 請求變得更快且更可靠。

    在 Linux x64 上,Bun 的 fetch() 每秒可以發送 155,000 個請求

    • 比 Node v18.9.0 的吞吐量高 24 倍
    • 比 Bun v0.1.11 的吞吐量高 6.2 倍
    • 比 Deno v1.25.3 的吞吐量高 4.5 倍
      image

    程式碼

    Bun 中 fetch 的效能似乎在最佳化原生 HTTP 基準測試工具(如 ohabombardier)的 25% 以內(更受歡迎的 autocannon 僅達到 6 萬 req/s)

    bun:ffi 中的 read.u8

    bun:ffi 中的 read 允許您讀取指標,而無需建立新的 DataView。這有助於編寫更快的函式庫。

    import { read, ptr } from "bun:ffi";
    import { it, expect } from "bun:test";
    
    it("read", () => {
      const buffer = new BigInt64Array(16);
      const dataView = new DataView(buffer.buffer);
      const addr = ptr(buffer);
    
      for (let i = 0; i < buffer.length; i++) {
        buffer[i] = BigInt(i);
        expect(read.intptr(addr, i * 8)).toBe(
          Number(dataView.getBigInt64(i * 8, true)),
        );
        expect(read.ptr(addr, i * 8)).toBe(
          Number(dataView.getBigUint64(i * 8, true)),
        );
        expect(read.f64(addr, i + 8)).toBe(dataView.getFloat64(i + 8, true));
        expect(read.i64(addr, i * 8)).toBe(dataView.getBigInt64(i * 8, true));
        expect(read.u64(addr, i * 8)).toBe(dataView.getBigUint64(i * 8, true));
      }
    
      for (let i = 0; i < buffer.byteLength - 4; i++) {
        // read is intended to behave like DataView
        // but instead of doing
        //    new DataView(toArrayBuffer(myPtr)).getInt8(0, true)
        // you can do
        //    read.i8(myPtr, 0)
        expect(read.i8(addr, i)).toBe(dataView.getInt8(i, true));
        expect(read.i16(addr, i)).toBe(dataView.getInt16(i, true));
        expect(read.i32(addr, i)).toBe(dataView.getInt32(i, true));
        expect(read.u8(addr, i)).toBe(dataView.getUint8(i, true));
        expect(read.u16(addr, i)).toBe(dataView.getUint16(i, true));
        expect(read.u32(addr, i)).toBe(dataView.getUint32(i, true));
        expect(read.f32(addr, i)).toBe(dataView.getFloat32(i, true));
      }
    });
    

    實作這個功能涉及對 WebKit 的 DOMJIT 進行更改,以啟用 52 位元整數參數(指標)

    這涉及對 bun:ffi 中指標表示形式進行不太可能但可能造成破壞性變更。先前,bun:ffi 指標將記憶體位址儲存在 JavaScript double 的末尾(將 double 位元轉換為 64 位元帶符號整數),而現在該值儲存在 double 的整數部分。這只會對依賴 napi 中指標表示形式的函式庫造成破壞性變更

    String.prototype.replace 速度提高 2 倍

    感謝 @ConstellationString.prototype.replace 在 Safari 和 Bun 中的速度提高了 2 倍。它會影響像這樣的程式碼

    myString.replace("foo", "baz");
    

    PR

    • https://github.com/WebKit/WebKit/pull/4079
    • https://github.com/WebKit/WebKit/pull/4121
    • https://github.com/WebKit/WebKit/pull/3983

    這個版本的 Bun 更新到截至 2022 年 9 月 17 日的最新 WebKit 版本(其中包括這些 PR)

    更快的 crypto.getRandomValuescrypto.randomUUID

    crypto.getRandomValues 現在使用 BoringSSL 的最佳化隨機函數

    注意:此螢幕截圖是在 Bun 的版本升級到 v0.1.12 之前拍攝的,因此顯示的是 v0.1.11

    image

    更多

    完整變更日誌