Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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.

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

fs.ReadFileSync

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

binding.open(…) node_file.cc

Slide 10

Slide 10 text

binding.open(…) node_file.cc

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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.

Slide 17

Slide 17 text

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).

Slide 18

Slide 18 text

Ryan’s diagram from the initial presentation:
 http://tinyclouds.org/jsconf2018.pdf

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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.

Slide 24

Slide 24 text

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(…)

Slide 25

Slide 25 text

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!

Slide 26

Slide 26 text

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*.

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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.

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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:

Slide 31

Slide 31 text

Golang vs Rust:
 interop constraints

Slide 32

Slide 32 text

Golang vs Rust:
 interop constraints • This is my hacky reimplementation of deno in rust (it’s called reno):
 https://github.com/matiasinsaurralde/reno

Slide 33

Slide 33 text

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).

Slide 34

Slide 34 text

My HTTP experiment

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

HTTP in deno?

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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).

Slide 40

Slide 40 text

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…

Slide 41

Slide 41 text

What’s next?

Slide 42

Slide 42 text

Thanks! Find deno here: https://github.com/denoland/deno Find me on:
 Twitter: @matias_baruch
 Github: matiasinsaurralde
 E-mail: [email protected]