🔧 AI Nachrichten Two Minute Papers: I Never Thought I’d See This Happen(10.09.2026 um 10:47 Uhr)
🔧 AI Nachrichten Google DeepMind: How AI is transforming weather prediction(09.09.2026 um 18:10 Uhr)
🔧 ProgrammierungCompiler Construction for Dummies (mrmcd26)(12.09.2026 um 00:00 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - SoK: The Constant Time Model(10.09.2026 um 00:26 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - SoK: Insecurity of Cellular Basebands(10.09.2026 um 00:26 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - A Dummy's Guide to Agentic Exploit Generation(10.09.2026 um 00:26 Uhr)
🔧 AI Nachrichten Two Minute Papers: I Never Thought I’d See This Happen(10.09.2026 um 10:47 Uhr)
🔧 AI Nachrichten Google DeepMind: How AI is transforming weather prediction(09.09.2026 um 18:10 Uhr)
🔧 ProgrammierungCompiler Construction for Dummies (mrmcd26)(12.09.2026 um 00:00 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - SoK: The Constant Time Model(10.09.2026 um 00:26 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - SoK: Insecurity of Cellular Basebands(10.09.2026 um 00:26 Uhr)
🕵️ SicherheitslückenUSENIX: WOOT '26 - A Dummy's Guide to Agentic Exploit Generation(10.09.2026 um 00:26 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 12 Min Lesezeit
0

How to and Should you use Bun FFI

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




What are we trying to achieve



Let's say you have a JavaScript application that runs in bun and you've identified some bottleneck that you'd like to optimize.

Rewriting it in a more performant language may just be the solution you need.



As a modern JS runtime, Bun supports Foreign Function Interface (FFI) to call libraries written in other languages that support exposing C ABIs, like C, C++, Rust and Zig.



In this post, we'll go over how one may use it, and conclude whether one can benefit from it.





How to link the library to JavaScript



This example is using Rust. Creating a shared library with C bindings looks differently in other languages but the idea remains the same.





From JS side



Bun exposes its FFI API through . Other languages that manage memory will have to do something similar.






Memory management



As we can see, it's possible to allocate memory in both JS and Rust, and neither can safely manage others memory.



Let's choose where you should allocate your memory and how.






Allocate in Rust



There are 3 methods of delegating memory cleanup to Rust from JS and all have their pros and cons.






Use FinalizationRegistry



Use







  • CODE
    function readStringU16(
    create_string_u16: (ptr: Uint16Array, len: number) => void,
    ): string {
    const length = 12;
    const buffer = new Uint16Array(length);
    create_string_u16(buffer, length)!;
    const decoder = new TextDecoder("utf-16");
    const copy = decoder.decode(buffer);
    return copy;
    }

    function readStringC(create_string_c: () => CString): string {
    const cstr = create_string_c();
    const copy = cstr.toString();
    return copy;
    }

    const readU16 = readStringU16.bind(null, create_string_u16);
    const readC = readStringC.bind(null, create_string_c);
    summary(() => {
    bench("read u16", readU16);
    bench("read c", readC);
    });
    await run({ colors: false });









    CODE
    const STRING: &str = "Hello, World";

    #[no_mangle]
    pub unsafe extern "C" fn create_string_u16(ptr: *mut u16, capacity: usize) {
    let buffer: &mut [u16] = unsafe { slice::from_raw_parts_mut(ptr, capacity) };
    let src: Vec<u16> = STRING.encode_utf16().collect::<Vec<u16>>();
    buffer.copy_from_slice(&src);
    }

    #[no_mangle]
    pub extern "C" fn create_string_c() -> *const c_char {
    ManuallyDrop::new(CString::new(STRING).unwrap()).as_ptr()
    }









    CODE
    benchmark              avg (min … max) p75   p99    (min … top 1%)
    -------------------------------------- -------------------------------
    read u16 1.12 µs/iter 1.21 µs █▂
    (905.96 ns … 1.83 µs) 1.79 µs ██▆▅▆▇▇▇▃▂▂▄▃▃▂▂▁▂▂▁▁
    read c 727.82 ns/iter 809.01 ns █▂
    (590.53 ns … 1.03 µs) 969.92 ns ▆███▆▆▇▃▆▄▄▆▃▄▆▆▃▂▃▂▂

    summary
    read c
    1.54x faster than read u16









    What about WebAssembly?



    It's time to address the elephant in the room that is WebAssembly.

    Should you choose nice existing WASM bindings over dealing with C ABI?



    The answer is probably neither.





    Is it actually worth it?



    Introducing another language to your codebase will require more than just a single bottleneck to be worth it DX-wise and performance-wise.



    Here is a benchmark for a simple range function in JS, WASM and Rust.




    CODE
    // rs.rs
    #[no_mangle]
    pub unsafe extern "C" fn rs_range(ptr: *mut i32, start: i32, end: i32) {
    let len: usize = usize::try_from(end - start).unwrap();
    let buffer: &mut [i32] = unsafe { slice::from_raw_parts_mut(ptr, len) };
    let src: Vec<i32> = (start..end).collect();
    buffer.copy_from_slice(&src);
    }

    // wasm.rs
    #[wasm_bindgen]
    pub fn wa_range(start: i32, end: i32) -> Vec<i32> {
    (start..end).collect()
    }









    CODE
    function tsRange(start: number, end: number): number[] {
    return [...Array(end - start).keys()].map((x) => x + start);
    }

    function wrapWa(
    wa_range: (start: number, end: number) => Int32Array,
    ): (start: number, end: number) => number[] {
    return (start, end) => {
    return Array.from(wa_range(start, end));
    };
    }

    function wrapRs(
    rs_range: (ptr: Int32Array, start: number, end: number) => void,
    ): (start: number, end: number) => number[] {
    return (start, end) => {
    const buffer = new Int32Array(end - start);
    rs_range(buffer, start, end);
    return Array.from(buffer);
    };
    }

    await init();
    const waRange = wrapWa(wa_range);
    const rsRange = wrapRs(rs_range);

    summary(() => {
    bench("ts", () => tsRange(100, 50000));
    bench("wa", () => waRange(100, 50000));
    bench("rs", () => rsRange(100, 50000));
    });
    await run({ colors: false });









    CODE
    benchmark              avg (min … max) p75   p99    (min … top 1%)
    -------------------------------------- -------------------------------
    ts 1.33 ms/iter 1.25 ms █
    (802.90 µs … 5.29 ms) 4.22 ms ▂██▅▂▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁
    wa 1.58 ms/iter 1.72 ms █
    (1.17 ms … 4.36 ms) 4.09 ms ██▄▃▄▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁
    rs 1.47 ms/iter 1.43 ms ▂█
    (1.17 ms … 4.11 ms) 3.84 ms ██▃▂▂▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

    summary
    ts
    1.1x faster than rs
    1.18x faster than wa






    Native library barely beats out WASM and consistently loses to the pure TypeScript implementation.



    And that's it for this tutorial for/exploration of bun:ffi module. Hopefully we all have walked away from this a little bit more educated.

    Feel free to share thoughts and questions in the comments

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
  • Wie bewertest du diesen Beitrag?
    1 Klick Feedback
    Teilen mit Netzwerk & Team:

    Community-Analysen & Experten-Meinungen 0

    Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
    Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
    Community Pulse: Relevanz-Einschätzung
    1 Klick Experten-Votum
    🔴 Akute Relevanz 0%
    🟡 In Evaluierung 0%
    🟢 Keine Auswirkung 0%
    Spannende Innovation 0%
    Verwandte Story-Cluster & Quellen (Vektor-KI)
    Port 8095 Engine
    10 Quellen
    GitHub Release: dependabot/dependabot-core v0.393.0 (24.08.2026)
    1 Quelle
    CC2tv #433: Was CachyOS anders macht als Linux Mint 🐧️
    1 Quelle
    Arti 2.6.0 released
    Ähnliche Beiträge
    🔍 Verwandte News

    Auch interessante Nachrichten How to and Should you use Bun FFI

    Thematisch verwandte Begriffe: Should · 6 Treffer

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...