# Deno, A New Server-Side Runtime - Ryan Dahl
{%hackmd dh921X26R26y_elFAEP5yg %}
###### tags: `jsdc2018`
---
## Slide
https://tinyclouds.org/deno_jsdc.pptx
## Video
- https://www.youtube.com/watch?v=FlTG0UXRAkE
{%youtube FlTG0UXRAkE %}
## Deno is a new server-side javascript runtime
It is attempting to solve serval problems
* Correct I/O interfaces
* Be secure by default
* Introduce a decentralized module system
## In UNIX everything is a file
Or better started "in UNIX everything is a File Descriptor"
The fundamental property or File Descriptors is that you can read(2) and/or write(2) to them.
This allows files. directories network connections and other programs to be composable.
## Traditional Blocking I/O
Traditional UNIX programs use blocking reads and writes to process data;
```c=
char buf[64];
size_t n;
for (;;){
// Different data streams abstracted as a FD, thus composable
n = read(SIDIN_FILENO, buf, 64);
if (n <= 0) break;
// Zero-copy, fixed buf allocation, thus: efficient
n = write(SIDOUT_FILENO, buf, n);
if (n <= 0) break;
}
```
## Traditional Blocking I/O is Simple, Efficient and correct
## In Node, everything is non-blocking
For ergonomic reasons, writes were made buffered but non-blocking.
```javascript=
process.stdout.write(data);
// continue.
```
This abstraction is in essence, dispatching an uncontrolled flow of events to the program
in GUIs, this doesn't matter because the event thoughtput is relatively small.
in high-concurrency servers, it does.
## Because of this tail latency in node can be quite bad under load.
## Go has its roots in Plan9.
(The experimental OS that took "Eveything is a File" to extreme lengths.)
It's intersting io look at how 25 ...
## Go's Reader/Writer is the modern ideal of UNIX
The interfaces model the read(2) write(2) syscalls without relying on FDs which imply expensive syscalls
Not every type of data stream needs a FD (file descriptor)
Without solving the memory overhead of pthreads, blocking functions like the wouldn't be useful for high-concurrency servers.
But they....
## Go is great, but dynamic languages arer still very useful
I spend most of my time in compiled languages like C++, Go, and Rust
But very offen ...
The abillity to dynamically script proper i/O pipeline
## JavaScript has evolved features in recent years that suggest rethingking some fundamental design choices of Node may be worthwhile.
* **ArrayBuffers** allows a proper standard way access to raw memory
* **TypeScript interfaces** allow composing very different implementations.
* **Async / Await** allows ergonomically waiting for events
## Expressing Reader/Writer in Modern JS
```typescript=
interface Reader {
reader(p: Unit8Array): Promise<{nread: number, eof: boolean}>;
}
interface Writer {
write(p: Unit8Array): Promise<number>;
}
```
## Building a runtime around Reader/Writer allows us to port other concepts, tests, and documentation from Go.
Good ideas should be reused - and there ...
## Example
### Cat.ts
This example implements a basic version of the UNIX cat utility
This demonstrates how Reader and Writer work
```typescript=
import { args, open, copy, stdout } from "deno";
async function main() {
for (let i = 1; i < args.length; i++) {
let filename = args[i];
let file = await open(filename);
await copy(stdout, file);
}
}
main();
```
I have posted the cat.ts program to a web server
### echo_server.ts
THis is an example fo a simple server which
- accepts connection
[echo_server.ts](https://deno.land/x/examples/echo_server.ts)
When this program is started, the user is prompted for permission:
```shell
$ deno https://deno.land/x/examples/echo_server.ts
```
>note: use `--alow-net` to access internet with explicit permission
To test it, try sending a HTTP request to it by using curl. The request gets written directly back to the client
## Linking to third party libraries
Like browser JavaScript. Deno can import libraries directly from URLs.
This example ...
Third party libraries are automatically downloaded
Linking to third party libraries
## Third party libraries are cached
Deno caches remote imports in sa special directory specified by the $DENO_DIR
Q: But what if https://deno.land/ goes down
**Production software should always bundle its dependencies.**
在 production 指定 `$DENO_DIR`,deno 會檢查資料夾中的套件,避免在 production 下載相依函式庫
Q: 怎麼指定套件版本號 How do your import to a specific version? URLs can change at any time.
simply specify the version in the URL
For example:
https://unpkg.com/liltest@0.0.5/dist/liltest.jb
Q: 在大型專案中每個地方都 import URL 很怪
import from the `package.ts` and avoid many references to the same URL:
```typescript=
// package.ts
export { test } from "https://deno.land/x/testing/testing.ts";
```
Elsewhere import from the package.ts
```typescript=
import { test } from "./package.ts";
```
## Documentation is still under construction.
However...
```shell
$ deno --types
```
prints the exact types used. including.
- Everything in the global namespace
- Everythings in the deno module
- ...
## Internal Design
### Deno is a new, 6 month old code base.
* like Node, built on V8
* The prototype implementation was done in Go.
* rewritten in **Rust** to avoid having two complex runtimes in the same process (in particular, two garbage collectors.)
* The **TypeScript** compiler is build-in to the deno executable. (Using V8 snapshots)
## Deno is secure by default
Like in the browser, user code is untrusted.
Permissions must be elevated using command line flags.
* `--allow-net` // Network
* `--allow-write` // File system write
* `--allow-env` // Environmental variables
* `--allow-run` // Subprocess execution
## Deno is like a userspace Operating System
Deno does not allow itself access to the V8 binding API.
Calls from user code (JS) to the pirvileged side (Rust) are performed though message serialized to ArrayBuffers.
There calls are called "Ops" and are the analog of syscalls.
The "op calling convention" used the [FlatBuffers serialization software](https://github.com/google/flatbuffers)
## Ops map JS Promises onto Rust Futures
Deno uses the [Tokio event loop](https://github.com/tokio-rs/tokio)
Tokio is built aroud the Future abstraction. The Rust analog of Promises
Deno has machinery to generally map Futures onto Promises. such that errors in Rust automatically map to Promise rejections.
```
type Op = Future<Item = Box<[u8]>, Error = DonoError> + send;
```
This allows us to quickly bind to third party Rust software.
Unlike Node, Deno handles ops asynchronously to the V8 thread. We expect this to result in less gitter - especially when we get to functionally like TLS or GZIP. (But we're not there yet.)
## Continuous Benchmarks
https://denoland.github.io/deno/all_benchmark.html
## What's next?
* Performance and stability improvements: we are still iterating heavily on the core event loop and compiler organization.
* HTTP Server: Rust's Hyper web server already compiled, but havent yet exposed a server interface
* Worker API: for spawning multiple intances of Deno.
* Rust Crate: We expect many users will want to build custom Deno instances into their own software
## Deno binaries are avaliable for Mac / Win / Linux
Follow the instructions at https://deno.land/
Deno ships a single executable, installable with a single command.
These slides: https://tinyclouds.org/deno_jsdc.pptx
---
[Deno's Github page](https://github.com/denoland/deno)