Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Deno: an experimental approach on V8 interoperability

Deno: an experimental approach on V8 interoperability

Matias Insaurralde

October 20, 2018
Tweet

More Decks by Matias Insaurralde

Other Decks in Programming

Transcript

  1. Deno: an experimental
    approach on V8 interop
    Matías Insaurralde - @matias_baruch

    View Slide

  2. Intro
    • 23 years old, living in Asunción, Paraguay !
    • Engineer at (we’re building an open
    source API gateway!).
    • I love FOSS and security topics.
    • Hobbies: meet random people, improvise
    music, eat pasta.

    View Slide

  3. Agenda
    • Overview of NodeJS syscalls.
    • What’s deno?
    • Go versus Rust: interop constraints
    • My HTTP experiment
    • What’s next?

    View Slide

  4. fs.ReadFileSync

    View Slide

  5. fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    tryStatSync(fd)
    tryReadSync(fd)
    fs.closeSync(fd)
    fs.js

    View Slide

  6. fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    tryStatSync(fd)
    tryReadSync(fd)
    fs.closeSync(fd)
    fs.js

    View Slide

  7. fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    fs.js

    View Slide

  8. fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    fs.js

    View Slide

  9. binding.open(…)
    node_file.cc

    View Slide

  10. binding.open(…)
    node_file.cc

    View Slide

  11. Open(…)
    “uv_fs_open” is the “open”
    wrapper provided by libuv.
    node_file.cc

    View Slide

  12. node_file.cc
    Open(…)
    “uv_fs_open” is the “open”
    wrapper provided by libuv.

    View Slide

  13. http://docs.libuv.org/en/v1.x/guide/filesystem.html

    View Slide

  14. http://man7.org/linux/man-pages/man2/open.2.html

    View Slide

  15. fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    binding.open(…) (node_file.cc)
    uv_fs_open(…) (libuv)
    open(…) (posix)

    View Slide

  16. What’s deno?
    • It’s a TypeScript runtime focused on
    security, built on V8.
    • No explicitly compatible with NodeJS
    (also: no npm, no package.json, etc.).
    • The initial prototype used a Golang
    backend, current one is written in Rust.
    C++ is used in a minimal way to bind V8
    to these alternative backends.

    View Slide

  17. What’s deno?
    • Network access, local FS access and env
    access disabled by default.
    • Syscalls are easier to audit and could
    provide a good security framework for
    some applications.
    • Minimal number of V8 interactions: send,
    recv (used for in-memory message
    passing).

    View Slide

  18. Ryan’s diagram from the initial presentation:

    http://tinyclouds.org/jsconf2018.pdf

    View Slide

  19. deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)

    View Slide

  20. deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    fs.readFileSync(“file.txt”)
    fd = fs.openSync(“file.txt”, …)
    binding.open(…) (node_file.cc)
    uv_fs_open(…) (libuv)
    open(…) (posix)
    deno
    node

    View Slide

  21. deno
    os.ts
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)

    View Slide

  22. deno
    os.go
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)

    View Slide

  23. in-memory

    pubusb

    message passing
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    Golang V8
    Channels
    os
    deno.readFileSync(…)

    Publishes a message
    containing the
    filename and other
    parameters.

    View Slide

  24. in-memory

    pubusb

    message passing
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    Golang V8
    Channels
    os
    deno.readFileSync(…)

    Publishes a message
    containing the
    filename and other
    parameters.
    After receiving
    the message, the
    dispatcher calls
    ReadFileSync(…)

    View Slide

  25. in-memory

    pubusb

    message passing
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    Golang V8
    Channels
    os
    ReadFileSync(…)

    Reads the file
    and publishes a
    message to the
    “os” channel,
    containing the
    file contents.
    We get the file
    contents!

    View Slide

  26. in-memory

    pubusb

    message passing
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    Golang V8
    Channels
    os
    net
    http
    The runtime can
    implement
    different
    channels for each
    required module.
    The messages are
    serialized using
    Protocol Buffers*.

    View Slide

  27. in-memory

    pubusb

    message passing
    fs.readFileSync(“file.txt”)
    deno.readFileSync(…) (TS wrapper/V8)
    ReadFileSync(…) (Golang)
    open(…) (posix)
    Rust V8
    Channels
    os
    net
    http

    View Slide

  28. Golang vs Rust:

    interop constraints
    • Go is a GCed language and doesn’t allow
    passing Go pointers to the native side
    (the opposite is possible though), this
    might result in unnecessary allocations
    under some circumstances.
    • Using deno with a Go backend involved
    two GCs! This is a potential issue ry
    mentioned and one of the reasons to
    replace Go with Rust, which it’s not
    GCed.

    View Slide

  29. Golang vs Rust:

    interop constraints
    • deno was able to start multiple V8
    workers but there’s no easy way of
    accessing these workers from the Go
    side, a “worker table” was used, involving
    a mutex as you can find in: https://
    github.com/ry/v8worker2
    • I did a Rust port of this library to continue
    my experiment: https://github.com/
    matiasinsaurralde/rust-v8worker2

    View Slide

  30. Golang vs Rust:

    interop constraints
    • The Rust port is way more efficient as you
    can handle interactions with the native
    world easily and keep passing pointers!
    • This is what my port looked like:

    View Slide

  31. Golang vs Rust:

    interop constraints

    View Slide

  32. Golang vs Rust:

    interop constraints
    • This is my hacky reimplementation of
    deno in rust (it’s called reno):

    https://github.com/matiasinsaurralde/reno

    View Slide

  33. My HTTP experiment
    • I began researching the architecture and
    initial implementation after the project was
    announced in JSConf (June 6, 2018).
    • The initial implementation used Golang
    and a simple dispatcher (very similar to the
    current one).

    View Slide

  34. My HTTP experiment

    View Slide

  35. View Slide

  36. View Slide

  37. HTTP in deno?

    View Slide

  38. What’s next?
    • The current implementation uses a new
    Rust backend.
    • Everything is contained on a single binary
    (a minimal V8 build is embedded into
    this).
    • Roadmap here: https://github.com/
    denoland/deno/blob/master/Roadmap.md

    View Slide

  39. What’s next?
    • The current implementation replaced
    Protocol Buffers with Flatbuffers: this is a
    great thing in terms of memory usage!
    • Browser compatibility is planned.
    • Experimental binaries are being released
    from time to time (Linux, Windows and
    OS X).

    View Slide

  40. What’s next?
    • Current implementation uses Tokio, an
    async runtime for Rust, replacing libuv in
    some ways.
    • HTTP support using the new Rust
    backend is in progress…

    View Slide

  41. What’s next?

    View Slide

  42. Thanks!
    Find deno here:
    https://github.com/denoland/deno
    Find me on:

    Twitter: @matias_baruch

    Github: matiasinsaurralde

    E-mail: [email protected]

    View Slide