Slide 1

Slide 1 text

Enclose.IO: current cutting- edges and the future work Minqi Pan

Slide 2

Slide 2 text

I’m Minqi Pan github.com/pmq20 twitter @psvr

Slide 3

Slide 3 text

We made some modifications to … • Node.js Compile-time • Node.js Link-time / Test-time • Node.js Run-time

Slide 4

Slide 4 text

Compile-time

Slide 5

Slide 5 text

• Serialize project files into structs of {path, *source, source_len} • Serialize raw file contents into array of bytes • Bonus of Compiler hints: the compiler can tell us the offsets of those JS scripts • (TODO) better usage of resource handling of the compiler

Slide 6

Slide 6 text

• TODO: maybe {path, *source, source_len, atime, mtime, ctime, birthtime} for fs.stat()? Anybody uses that info? • TODO: better record dir, for fs.readdir

Slide 7

Slide 7 text

• skip ParseArgs • (cf. in Start(), ParseArgs is called before StartNodeInstance and CreateEnvironment)

Slide 8

Slide 8 text

• checks for memfs in process.argv[1] • customized entrance via automatically setting process.argv[1] • e.g. process.argv[1]="/__enclose_io_memfs__/ node_modules/coffee-script/bin/coffee" • (cf. ExecuteString called on bootstrap_node.js when LoadEnvironment)

Slide 9

Slide 9 text

• special treatment of __enclose_io_fork__ • special treatment of ENCLOSE_IO_USE_ORIGINAL_NODE

Slide 10

Slide 10 text

• adds MEMFS::stat_file • adds MEMFS::stat_dir • adds MEMFS::resolve

Slide 11

Slide 11 text

• adds MEMFS::exists? • adds MEMFS::read_file • adds MEMFS::read_dir

Slide 12

Slide 12 text

• (TODO) simulate file descriptors • (TODO) Libmemfs: a portable, pure C implementation of a Unix-style, read-only, in- memory filesystem.

Slide 13

Slide 13 text

Link-time / Test-time

Slide 14

Slide 14 text

• Enforces static linking • copies routines of openssl, libuv, … into the executable image • (TODO) copy C extensions like fsevents used by the project into the executable image • problem of GLIBC and GLIBCXX

Slide 15

Slide 15 text

passes original tests

Slide 16

Slide 16 text

add Enclose-specific tests

Slide 17

Slide 17 text

Runtime

Slide 18

Slide 18 text

• the program is loaded into memory • your serialized project files are initially stored in .text, are then “copied” by the OS into the data segment (.data) of the program virtual address space during start-up • (cf.) text segment, the “REAL” executable instructions, read-only and has a fixed size • (TODO) read-only data segment (.rodata)

Slide 19

Slide 19 text

– Wikipedia: Loader (computing) “In the case of operating systems that support virtual memory, the loader may not actually copy the contents of executable files into memory, but rather may simply declare to the virtual memory subsystem that there is a mapping between a region of memory allocated to contain the running program's code and the contents of the associated executable file.”

Slide 20

Slide 20 text

– Wikipedia: Loader (computing) “The virtual memory subsystem is then made aware that pages with that region of memory need to be filled on demand if and when program execution actually hits those areas of unfilled memory. This may mean parts of a program's code are not actually copied into memory until they are actually used, and unused code may never be loaded into memory at all.”

Slide 21

Slide 21 text

• String::NewFromUtf8 during start-up • need to copy memory when passed to V8 • from data segment to the heap, what a PAIN!

Slide 22

Slide 22 text

• (TODO) to speed up startup, use zero-copy external string resources, V8 no longer requires that strings are aligned if they are one-byte strings (string data must be immutable and that the data must be Latin-1 and not UTF-8, which would require special treatment internally in the engine and do not allow efficient indexing)
 
 V8 3.20.9 enforces that external pointers are aligned on a two-byte boundary (cf. Tagged pointers, objects are always at least 4-byte aligned, and we can never have a pointer to the middle of an object in JavaScript) • (TODO) maybe zero-copy buffers?

Slide 23

Slide 23 text

• (TODO) to speed up startup, delay String::NewExternalOneByte only when accessed, not running literally millions of String::NewFromUtf8/ String::NewExternalOneByte at start up

Slide 24

Slide 24 text

• require first finds in memfs • require.resolve first resolves in memfs

Slide 25

Slide 25 text

• fs.readFile, fs.readFileSync: first checks for memfs path • fs.readdir: first checks for memfs path

Slide 26

Slide 26 text

• fs.fstat, fs.lstat, fs.lstatSync, fs.statSync: first checks for memfs path • fs.watch, fs.watchFile: does not watch for memfs • fs.realpathSync: first checks for memfs path

Slide 27

Slide 27 text

• child_process.fork needs the original argv[1] semantic • will set __enclose_io_fork__ as argv[1] in child_process.fork

Slide 28

Slide 28 text

• child_process.spawn(…process.execPath…) needs the original node semantic • will set ENCLOSE_IO_USE_ORIGINAL_NODE

Slide 29

Slide 29 text

Future Work • see previous TODO’s • only include JS scripts that can be referenced • only include symbols that can be referenced • generate unoptimized machine code in compile- time via v8, no sources required in runtime

Slide 30

Slide 30 text

Thank you! https://github.com/enclose-io