B ROWSIX: Bridging the Gap Between Unix and the Browser
Bobby Powers, John Vilk, Emery D. Berger
University of Massachusetts Amherst{bpowers, jvilk, emery}@cs.umass.edu

Abstract

CCS Concepts • Information systems → Browsers;• Software and its engineering → Operating systems

Applications written to run on conventional operating systems
typically depend on OS abstractions like processes, pipes,
signals, sockets, and a shared file system. Porting theseapplications to the web currently requires extensive rewritingor hosting significant portions of code server-side becausebrowsers present a nontraditional runtime environment thatlacks OS functionality.
This paper presents B ROWSIX, a framework that bridges
the considerable gap between conventional operating systems and the browser, enabling unmodified programs expecting a Unix-like environment to run directly in the browser.
B ROWSIX comprises two core parts: (1) a JavaScript-onlysystem that makes core Unix features (including pipes, concurrent processes, signals, sockets, and a shared file system)
available to web applications; and (2) extended JavaScript runtimes for C, C++, Go, and Node.js that support running programs written in these languages as processes in the browser.
B ROWSIX supports running a POSIX shell, making it straightforward to connect applications together via pipes.
We illustrate B ROWSIX’s capabilities via case studies that
demonstrate how it eases porting legacy applications to thebrowser and enables new functionality. We demonstrate a
B ROWSIX-enabled LATEX editor that operates by executing
unmodified versions of pdfLaTeX and BibTeX. This browseronly LATEX editor can render documents in seconds, making
it fast enough to be practical. We further demonstrate how
B ROWSIX lets us port a client-server application to run
entirely in the browser for disconnected operation. Creatingthese applications required less than 50 lines of glue code andno code modifications, demonstrating how easily B ROWSIX
can be used to build sophisticated web applications fromexisting parts without modification.

Keywords Browsix, browser, operating system, JavaScript1.

Web browsers make it straightforward to build user interfaces, but they can be difficult to use as a platform to build
sophisticated applications. Code must generally be writtenfrom scratch or heavily modified; compiling existing code or
libraries to JavaScript is not sufficient because these applications depend on standard OS abstractions like processes anda shared file system, which browsers do not support. Many
web applications are thus divided between a front-end UI thatruns in the browser and a backend server. The backend runs
on a traditional operating system, where the application cantake advantage of familiar OS abstractions and run a wide
variety of off-the-shelf libraries and programs.
As a representative example, websites like ShareLaTeX1and Overleaf2 let users write and edit LATEX documents inthe browser without the need to install a TEX distribution
locally. This workflow lowers the barrier for students andfirst-time LATEX authors and enables real-time collaboration,
eliminating some of the complexity of creating multi-author
documents. These applications achieve this functionality byproviding a browser-based frontend for editing; user input issent to the server for persistence and collaboration purposes.
When the user requests a generated PDF, the website runs
pdflatex and bibtex server-side on the user’s behalf, withthe resulting PDF sent to the browser when complete.
These web applications generate PDFs server-side outof necessity because browsers lack the operating systemservices and execution environment that Unix programs
expect. Creating PDFs from LATEX requires spawning multiple
processes to run pdflatex and bibtex, which need to readfrom and write to a shared file system. If PDF generation
takes too long and the user cancels the request, the applicationneeds to send a SIGTERM or SIGKILL signal to clean up
any running processes. If PDF generation encounters anerror, the application needs to pipe the output of the relevant
process back to the client over the network. Since browsers

Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without
fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this noticeand the full citation on the first page. Copyrights for components of this work owned by others than the author(s) must
be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute tolists, requires prior specific permission and/or a fee. Request permissions from permissions@acm.org.
ASPLOS ’17

Introduction

April 8–12, 2017, Xi’an, China.

© 2017 Copyright held by the owner/author(s). Publication rights licensed to ACM.
ISBN 978-1-4503-4465-4/17/04. . . $15.00

1 https://www.sharelatex.com/

DOI: http://dx.doi.org/10.1145/3037697.3037727

2 https://www.overleaf.com/

253

do not support processes, signals, pipes, sockets, or a sharedfilesystem, they cannot perform any of these steps without
program modification.
Previous attempts to cope with this impedance mismatch
between conventional applications and the browser fall shortof providing the environment needed by many programs (seeSection 7). Emscripten and Doppio provide a POSIX-like runtime system for single processes, including a single-process
file system, limited support for threads, synchronous I/O, andproxying support for TCP/IP sockets [13, 16]. While thesesingle-process runtimes are useful for some applications, they
are severely limited because they are unable to provide therange of operating system functionality that many legacy
applications demand.
To overcome these limitations, we introduce B ROWSIX,a framework that brings Unix abstractions to the browser
through a shared kernel and common system-call conventions,bridging the gap between conventional operating systems andthe browser. B ROWSIX consists of two core components:(1) a JavaScript-only operating system that exposes a widearray of OS services that applications expect (including
pipes, concurrent processes, signals, sockets, and a shared
file system); and (2) extended JavaScript runtimes for C,
C++, Go, and Node.js that let unmodified programs written
in these languages and compiled to JavaScript run directlyin the browser. Because B ROWSIX’s components are written
entirely in JavaScript and require no plugins, applications
using B ROWSIX can run in a wide range of unmodified
modern web browsers including Google Chrome, Mozilla
Firefox, Apple Safari, and Microsoft Edge. B ROWSIX makes
it possible to port a wide range of existing applications andtheir language runtimes to the browser by providing the corefunctionality of a full operating system:• Processes: B ROWSIX implements a range of process
related system calls (including fork, spawn, exec, andwait4) and provides a process primitive on top of Web
Workers, letting applications run in parallel and spawn
subprocesses.

Figure 1: A LATEX editor built using B ROWSIX. B ROWSIX’s
OS services and language runtimes make it possible to run
complex legacy code (including pdflatex and bibtex)
directly in the browser, without code modifications (See
Section 2 for details.)(Go), and Node.js (JavaScript) to allow unmodified applications written in these languages to run directly asprocesses in the browser. Through its simple system callAPI, developers can straightforwardly integrate B ROWSIX
into additional language runtimes.
B ROWSIX dramatically simplifies the process of porting
complex applications to the browser environment. As ademonstration, we have built a LATEX editor that runs entirely
within the browser. When the user requests a PDF, B ROWSIX
runs make to re-build the document with pdflatex andbibtex, and pipes their standard output and standard error to
the application. These TEX programs use B ROWSIX’s shared
file system to read in the user’s source files, and any packages,
class files, and fonts referenced within, as in a traditional Unix
environment. The filesystem transparently loads any needed
external packages from the TeX Live distribution over HTTP
upon first access. Subsequent accesses to the same files are
instantaneous, as the browser caches them. While a full TeX
Live distribution is several gigabytes in size, a typical paper
only needs to retrieve several megabytes worth of packages
before it can be built. If the user cancels PDF generation,
B ROWSIX sends a SIGKILL signal to these processes. If
PDF generation fails, the application can display the captured
standard out and standard error. The result is serverless PDF
generation composed from off-the-shelf parts, with minimalengineering effort required to glue them together.
We demonstrate the utility of B ROWSIX with two further case studies. Using B ROWSIX, we build an applicationthat dynamically routes requests to a remote server or an inB ROWSIX server, both compiled from the same source code,
depending on the client’s performance and battery characteristics. We also use B ROWSIX to build a UNIX terminal
exposing a POSIX shell, enabling developers to launch andcompose applications and inspect B ROWSIX state in a familiar way.

• Signals: B ROWSIX supports a substantial subset of the

POSIX signals API, including kill and signal handlers,
letting processes communicate with each other asynchronously.
• Shared Filesystem: B ROWSIX lets processes share statethrough a shared FS.
• Pipes: B ROWSIX exposes the standard pipe API, mak-ing it simple for developers to compose processes into
pipelines.
• Sockets: B ROWSIX supports TCP socket servers andclients, making it possible to run server applications likedatabases and HTTP servers together with their clients inthe browser.
• Language Agnostic: B ROWSIX includes integration withthe runtime libraries of Emscripten (C/C++), GopherJS

254

Contributions

Once all steps have completed (or an error has occurred),the Make process exits with an exit code indicating whether or
not PDF generation succeeded. B ROWSIX sends the exit code
back to the web application. If GNU Make exits normally, theeditor reads the PDF from B ROWSIX’s shared filesystem anddisplays it to the user. Otherwise, it displays the standard output from pdflatex and bibtex to the user, which describes
the source of the error.

This paper makes the following contributions:• Bringing OS Abstractions and Services to the Browser.

We demonstrate that it is possible to provide a wide range
of key Unix abstractions and services in the browser on topof existing web APIs. We implement these in B ROWSIX, a
JavaScript-only framework featuring a kernel and system
calls that runs on all modern browsers (§3).

2.2• Runtime Integration for Existing Languages. We ex-

Building any web application that runs Unix programs in
B ROWSIX generally consists of the same three step process:(1) compile the programs to JavaScript (using tools withB ROWSIX support), (2) stage files required by the application
for placement in the in-browser filesystem, and (3) add setup
code to the web application to initiate B ROWSIX and launch
the programs.

tend the JavaScript runtimes of Emscripten (a C/C++ to
JavaScript toolchain), GopherJS (a Go to JavaScript compiler), and Node.js with B ROWSIX support, letting unmodified C, C++, Go, and Node.js programs execute and interoperate with one another within the browser as B ROWSIX
processes (§4).
• Case Studies. We demonstrate B ROWSIX’s utility bybuilding a LATEX editor, a serverless client-server web application, and a Unix terminal out of off-the-shelf components without modification. We characterize B ROWSIX’s
performance under these case studies and with microbenchmarks (§5) and show that its overhead is low
enough for real-world usage.

Compiling to JavaScript: To run pdflatex, bibtex, andGNU Make in B ROWSIX, the developer compiles each program to JavaScript using Emscripten, a C/C++ to JavaScript
compiler [16]. We extend Emscripten’s runtime library withB ROWSIX support, so standard Unix APIs map to B ROWSIX
primitives. We discuss this extension in more detail in Section 4.3.
Before compilation, the developer determines if any of the
programs use the fork command. Due to browser limitations
explored in Section 6, B ROWSIX can only implement fork
as an asynchronous system call, which requires the use of avariant of Emscripten’s compilation procedure that generates
less efficient code. If this option is configured incorrectly, theprogram will fail at runtime when it attempts to invoke fork.
For the LATEX case study, only GNU Make uses fork andrequires this setting.
From this point, the build process is mostly unchanged
from a standard compilation. For programs that use the autotools build system, such as GNU Make and TeX Live,instead of running ./configure, the developer invokes
emconfigure ./configure. This wrapper overrides standard tools like cc and ar with em prefixed alternatives thatcompile the program with Emscripten, producing individual
JavaScript files for each program.

• Guidance for Future Browsers. Based on our experi-ence writing B ROWSIX, we discuss current browser limitations and propose solutions (§6).

2.

B ROWSIX Overview

To give an overview of B ROWSIX’s features, this section
walks through the process of using B ROWSIX to build anin-browser LATEX editor using TeX Live utilities and GNU
Make. Figure 1 displays a screenshot of the editor.
2.1

Building with B ROWSIXLATEX Editor Overview

The editor presents a split-screen view to the user, with the
document’s LATEX source on the left, and generated PDF
preview on the right. The editor’s UI is a standard web
application, and represents the only new code. When the user
clicks on the “Build PDF” button, the editor uses B ROWSIX
to invoke GNU Make in a B ROWSIX process, which rebuilds
the PDF.
The process for building the PDF is familiar to anyone who
has used LATEX, except B ROWSIX performs all of the needed
steps entirely in the browser instead of server-side. It runs
GNU Make to read a Makefile from B ROWSIX’s file system,
which contains rules for rebuilding LATEX projects. Make thenruns pdflatex and bibtex, depending on whether the user
has updated the references file.
pdflatex and bibtex read any required LATEX packages,
fonts, and other system files from B ROWSIX’s file system,
which lazily pulls in files as needed from the network. Bothof these applications write their output to B ROWSIX’s filesystem.

Staging the Filesystem: The developer next configures
B ROWSIX’s in-browser filesystem so that it hosts all of
the files that the programs require. B ROWSIX’s file system
extends Doppio’s BrowserFS file system with multi-process
support, building on its support for files backed by cloudstorage, browser-local storage, traditional HTTP servers, andmore [13].
For our LATEX example, both pdflatex and bibtex require read access to class, font, and other files from a LATEX
distribution to function properly. While a complete TeX Live
distribution contains over 60,000 individual files, the average
LATEX document only references a small subset of these files.

255

To reduce load times and minimize the amount of storage
required on a client’s device, the developer can leverage
B ROWSIX’s filesystem to load only the needed files. In thiscase, the developer uploads a full TeX Live distribution to an
HTTP server and configures B ROWSIX’s filesystem to usean HTTP-backed filesystem backend. The filesystem willthen load these files on-demand from the network upon first
access. The browser caches these files automatically, making
subsequent access much faster.

Component
KernelBrowserFS modifications
Shared syscall module
Emscripten integration*(C/C++ support)
GopherJS integration*(Go support)
Node.js integration*TOTAL

B ROWSIX Setup Code: Finally, the developer adds code to
the web application to load and initialize B ROWSIX, and tolaunch make to build the PDF. A script tag in the HTMLloads browsix.js, and a subsequent script tag with inline
JavaScript calls B ROWSIX’s Boot function with the desired
filesystem configuration.
Additional application-specific initialization follows as
usual. Once the filesystem is ready, the developer adds
code to read the contents of main.tex and main.bib fromB ROWSIX’s filesystem, and display the contents in the editor.
Then, the application registers a callback function with the“Build PDF” button to run whenever the user clicks the button.
2.3

926
1,742
8,126

Figure 2: B ROWSIX components. * indicates these components are written in JavaScript, while the rest of thecomponents are written in TypeScript (which compiles to
JavaScript).
3.1

KernelThe kernel lives in the main JavaScript context alongside
the web application and acts as the intermediary between
processes and loosely coupled Unix subsystems. Processes
issue system calls to the kernel to access shared resources, andthe kernel routes these requests to the appropriate subsystem.
When the subsystem responds to the system call, it relays the
response to the process. The kernel is also responsible fordispatching signals to processes, which we describe further
in Section 3.3. Figure 3 presents a partial list of the system
calls that the kernel currently supports.
In a departure from modern Unix systems, B ROWSIX
does not support multiple users. A traditional kernel, forexample, uses user identities to check permissions on certain
system calls or for access to files. Unlike a traditional kernel,
B ROWSIX executes as a JavaScript library on a webpage. As
a result, B ROWSIX can rely on the browser’s built-in sandbox
and security features, such as the same origin policy, to isolate
the B ROWSIX kernel from the underlying operating systemand other web origins. In other words, a B ROWSIX applicationand its users enjoy the same level of protection and security
as any other web application.

Execution with B ROWSIXWhen the application’s callback is executed in response to auser’s “Build PDF” click, the application invokes the system
method on its kernel instance to start make. Make runs
pdflatex and bibtex as described in Section 1. When theapplication receives a notification from B ROWSIX that Make
has exited, it inspects Make’s exit code. If it is zero, the PDF
was generated successfully and is read from the filesystem.
Otherwise, the captured standard output and standard error
are displayed to the user so they can debug their markup.
This overview demonstrates how straightforward B ROWSIX
makes it to take existing components that were designed towork in a Unix environment and execute them seamlessly
inside a web browser. The next two sections provide technicaldetails on how B ROWSIX provides Unix-like abstractionsin the browser environment and integrates with language
runtimes.

3.

Lines of Code (LoC)
2,249
1,231
421
1,557

3.2

System Calls

The B ROWSIX kernel supports two types of system calls:
asynchronous and synchronous. Asynchronous system calls
work in all modern browsers, but impose a high performance
penalty on C and C++ programs. Synchronous system calls
enable higher performance for C and C++ programs in development versions of Chrome, Firefox, and Safari via a mechanism we describe below; this mechanism is already standardized and is on track to be supported by other mainstream
browsers.

B ROWSIX OS Support

The core of B ROWSIX’s OS support is a kernel that controls
access to shared Unix services. Unix services, including
the shared file system, pipes, sockets, and task structures,live inside the kernel, which runs as a JavaScript library inthe main browser thread. Processes run separately and inparallel inside Web Workers, and access B ROWSIX kernel
services through a system call abstraction. B ROWSIX andall of its runtime services are implemented in JavaScript and
TypeScript, a typed variant of JavaScript that compiles down
to vanilla JavaScript. Figure 2 provides a breakdown of eachof B ROWSIX’s components.

Asynchronous System Calls: B ROWSIX implements asynchronous system calls in a continuation-passing style (CPS).
A process initiates a system call by sending a message tothe kernel with a process-specific unique ID, the system call256

ClassProcess Managementwith two offsets into the heap: where to put system call return
values, and an offset to use to wake the process when thesyscall is complete.
A process invokes a synchronous system call by sendinga message as in the asynchronous case, but with arguments
limited to integers and integer offsets (representing pointers) into the shared memory array, rather than objects (likeArrayBuffers) that would need to be copied between heaps.
For system calls like pread, data is copied directly from thefilesystem, pipe or socket into the process’s heap, avoiding a
potentially large allocation and extra copy.
After sending a message to the kernel, the process performs a blocking wait on the offset into the SharedArrayBuffer previously arranged with the kernel and is awakened
when the system call has completed or a signal is received.
This wait is provided by the JavaScript Atomics.wait function, part of the ECMAScript Shared Memory and Atomics
specification [6]. A consequence of this approach is that fork
is not compatible with synchronous system calls, as there is
no way to rewind, continue, or jump to a particular call stackin the child Web Worker.
Synchronous system calls are faster in practice for a number of reasons. First, they only require one message to bepassed between the kernel and process, which is a relatively
slow operation. Second, system call arguments are numbers,
rather than potentially large arrays that need to be copied between JavaScript contexts. Finally, synchronous system calls
provide a blocking primitive and do not depend on language
runtimes to unwind and rewind the call stack. As such, they
are suitable for use with asm.js and WebAssembly functions on the call stack, which are faster and more amenable
to optimization by the JavaScript runtime than Emscripten’sinterpreter.
Synchronous system calls require two features: SharedArrayBuffers and Atomics. These are available in Firefox
Nightly, Safari Technology Preview, as well as Google
Chrome when SharedArrayBuffer support is enabled inchrome://flags. SharedArrayBuffers and Atomics aredraft web standards and are on track to be part of standard
versions of all mainstream browsers [6].

System calls
fork, spawn, pipe2,
wait4, exit

Process Metadatachdir, getcwd, getpid

Sockets

socket, bind, getsockname,listen, accept, connect

Directory IO

readdir, getdents,
rmdir, mkdir

File IO

open, close, unlink,llseek, pread, pwrite

File Metadata

access, fstat, lstat,
stat, readlink, utimes

Figure 3: A representative list of the system calls implemented by the B ROWSIX kernel. fork is only supported
for C and C++ programs.
number, and arguments. B ROWSIX copies all arguments, suchas file descriptor or a buffer to write to a file descriptor, fromthe process to the kernel - no memory is shared. When the
kernel sends a response, the Web Worker process executes thecontinuation (or callback) with response values, also copiedfrom the kernel’s heap into the process’s heap.
Asynchronous system calls work well for Node.js and Go,
but are only required for C and C++ programs that depend on
fork. In Node.js, the filesystem and other APIs accept a callback function to continue execution when the API’s result isavailable, which maps directly onto B ROWSIX asynchronous
system calls. The GopherJS runtime provides first-class support for suspending and resuming the call stack in order toimplement goroutines (lightweight thread-like primitives),
making it straightforward to resume from asynchronous system calls as well. However, C and C++ programs using fork
must be compiled in an interpreted mode (called the Emterpreter3 ) in order to save and restore the stack. This mode
produces bytecode that is in turn interpreted by a JavaScript
program at execution time. By contrast the standard asm.js4
output Emscripten produces is directly JIT compiled andexecuted by the browser’s JavaScript engine, which is substantially faster than executing bytecode in the Emterpreter.
Most C and C++ programs do not use fork and are able tobe compiled as asm.js with synchronous system calls.

3.3

Processes

B ROWSIX relies on Web Workers as the foundation for emulating Unix processes. However, Web Workers differ substantially from Unix processes, and B ROWSIX must provide
a significant amount of functionality to bridge this gap.
In Unix, processes execute in isolated virtual address
spaces, run in parallel with one another when the system has
multiple CPU cores, and can interact with system resourcesand other processes via system calls. However, the webbrowser does not expose a process API to web applications.
Instead, web applications can spawn a Web Worker that runs
a JavaScript file in parallel with the application.
A Web Worker has access to only a subset of browser interfaces (notably excluding the Document Object Model

Synchronous System Calls: Synchronous system calls
work by sharing a view of a process’s address space between the kernel and the process, similar to a traditional
operating system kernel like Linux. At startup, the language
runtime in a process wishing to use synchronous system
calls passes to the kernel (via an asynchronous system call)a reference to the heap (a SharedArrayBuffer object), along
3 https://github.com/kripken/emscripten/wiki/Emterpreter/
4 http://asmjs.org/

257

(DOM)), runs in a separate execution context, and can
only communicate with the main browser context via asynchronous message passing. Web Workers are not aware of
one another, cannot share memory with one another, and can
only exchange messages with the main browser context thatcreated them (see Section 6 for a discussion). Major browsers
like Chrome and Safari do not support spawning sub-workers
from workers, so-called nested workers, and have not added
support for them since they were first proposed in 2009. Thus,
if a Web Worker needs to perform a task in parallel, it mustdelegate the request to the main browser thread, and proxy all
messages to that worker through the main browser thread. Perhaps unsurprisingly, the limitations and complexity of Web
Workers have hindered their adoption in web applications.
By contrast, B ROWSIX implements Unix processes on
top of Web Workers, giving developers a familiar and fullfeatured abstraction for parallel processing in the browser.
Each B ROWSIX process has an associated task structure in
the kernel that contains its process ID, parent’s process ID,
Web Worker object, current working directory, and map of
open file descriptors. Processes have access to the system
calls in Figure 3, and invoke them by sending a message
with the system call name and arguments to the kernel. As
a result, processes can share state via the file system, send
signals to one another, spawn sub-processes to perform tasks
in parallel, and connect processes together using pipes. Below,
we describe how B ROWSIX maps familiar OS interfaces onto
Web Workers.

The second challenge is that there is no way to pass data
to a Worker on startup apart from sending a message. As
processes synchronously access state like the arguments
vector and environment map, B ROWSIX-enabled runtimes
delay execution of a process’s main() function until after
the worker has received an “init” message from the kernel
containing the process’s arguments and environment.
fork: The fork system call creates a new process containing a copy of the current address space and call stack. Fork
returns twice – first with a value of zero in the new process,and with the PID of the new process in the original. Web
Workers do not expose a cloning API, and JavaScript lacks
the reflection primitives required to serialize a context’s entire
state into a snapshot. Thus, B ROWSIX only supports fork
when a language runtime is able to completely enumerate andserialize its own state. Section 4 describes how we extend
Emscripten to provide fork support for C/C++ programs
compiled to JavaScript.
wait4: The wait4 system call reaps child processes thathave finished executing. It returns immediately if the specified
child has already exited, or the WNOHANG option is specified.
Waiting requires that the kernel not immediately free task
structures, and required us to implement the zombie taskstate for children that have not yet been waited upon. The
C library used by Emscripten, musl, uses the wait4 systemcall to implement the C library functions wait, wait3, andwaitpid.
exit: Language runtimes with B ROWSIX-support are required to explicitly issue an exit system call when they aredone executing, as the containing Web Worker context has
no way to know that the process has finished. This is due tothe event-based nature of JavaScript environments – even if
there are no pending events in the Worker’s queue, the main
JavaScript context could, from the perspective of the browser,
send the Worker a message at any time.

spawn: B ROWSIX supports spawn, which constructs a newprocess from a specified executable on the file system. spawn
is the primary process creation primitive exposed in modern programming environments such as Go and Node.js, as
fork is unsuitable for general use in multithreaded processes.
spawn lets a process specify an executable to run, the arguments to pass to that executable, the new process’s working
directory, and the resources that the subprocess should inherit(such as file descriptors). In B ROWSIX, executables include
JavaScript files, file beginning with a shebang line, and WebAssembly files. When a process invokes spawn, B ROWSIX
creates a new task structure with the specified resources andworking directory, and creates a new Web Worker that runs
the target executable or interpreter.
There are two technical challenges to implementing
spawn. First, the Web Worker constructor takes a URL to a
JavaScript file as its first argument. Files in B ROWSIX’s filesystem may not correspond to files on a web server. For example, they might be dynamically produced by other B ROWSIX
processes. To work around this restriction, B ROWSIX generates a JavaScript Blob object that contains the data in thefile, obtains a dynamically-created URL for the blob from thebrowser’s window object, and passes that URL as a parameterto the Web Worker constructor. All modern web browsers
now support constructing Workers from blob URLs.

getpid, getppid, getcwd, chdir: These four system
calls operate on data in the current process’s task structure,
which lives in the B ROWSIX kernel. getpid returns the process’s ID, getppid returns the parent process’s ID, getcwd
returns the process’s working directory, and chdir changes
the process’s working directory.
3.4

Pipes

B ROWSIX pipes are implemented as in-memory buffers withwait queues. If there is no data to be read when a process
issues a read system call, B ROWSIX enqueues the callback
encapsulating the system call response which it invokes whendata is written to the pipe. Similarly, if there is not enough freespace in a pipe’s internal buffer for a write request, B ROWSIX
waits until enough space frees up in the buffer from readrequests to complete the write.

258

3.5

Sockets

kernel . system (’ pdflatex example . tex ’,function ( pid , code ) {if ( code === 0) {displayPDF () ;} else {d is pl ay Latex Lo g () ;}} , logStdout , logStderr ) ;B ROWSIX implements a subset of the BSD/POSIX socket
API, with support for SOCK STREAM (TCP) sockets for communicating between B ROWSIX processes. These sockets enable servers that bind, listen and then accept new connections on a socket, along with clients that connect to asocket server, with both client and server reading and writingfrom the connected file descriptor. Sockets are sequenced,
reliable, bi-directional streams.
3.6

Figure 4: Creating a B ROWSIX process from JavaScript.

Shared File System

4.1

B ROWSIX builds on and significantly extends BrowserFS’s
file system, part of Doppio [13]. BrowserFS already included
support for multiple mounted filesystems in a single hierarchical directory structure. BrowserFS provides multiple filesystem backend implementations, such as in-memory, zip
file, XMLHttpRequest, Dropbox, and an overlay filesystem.
BrowserFS provides a unified, encapsulated interface to allof these backends.
B ROWSIX extends BrowserFS in two key ways: it adds
multi-process support and incorporates improved support for
loading files over HTTP. To provide multi-process support,
B ROWSIX’s file system adds locking operations to the overlay
filesystem to prevent operations from different processes frominterleaving. In addition, B ROWSIX incorporates domainspecific optimizations into its file system; for example, it
avoids expensive operations like recording the call stack whena path lookup fails (a common event).
B ROWSIX modifies BrowserFS’s overlay backend to lazily
load files from its read-only underlay; the original version
eagerly read all files from the read-only filesystem upon
initialization. B ROWSIX’s approach drastically improves thestartup time of the kernel, minimizes the amount of datatransferred over the network, and enables applications likethe LATEX editor where only a small subset of files are required
for a given end user.
Finally, B ROWSIX implements system calls that operate
on paths, like open and stat, as method calls to the kernel’s
BrowserFS instance. When a system call takes a file descriptor as an argument, the kernel looks up the descriptor in thetasks’s file hashmap and invokes the appropriate method onthat file object, calling into BrowserFS for regular files anddirectories. Child processes inherit file descriptor tables, and
B ROWSIX explicitly manages each object (whether it is a file,
directory, pipe or socket) with reference counting.

4.

Browser Environment Extensions

Web applications run alongside the B ROWSIX kernel in themain browser context, and have access to B ROWSIX features
through several global APIs. B ROWSIX exposes new APIs
for process creation, file access, and socket notifications, andan XMLHttpRequest-like interface to send HTTP requests to
B ROWSIX processes.
To start a B ROWSIX process the client application invokes
an API similar to C’s system, as seen in Figure 4. In addition
to specifying the program to run and arguments, callbacks are
passed to B ROWSIX that are invoked when data is available on
standard out, standard error and upon program exit. B ROWSIX
additionally provides APIs to enable the client to create, read,
and write files.
Socket notifications let applications register a callback to
be invoked when a process has started listening on a particular
port. These notifications let web applications launch a server
as a process and appropriately delay communicating with theserver until it is listening for messages. Web applications do
not need to resort to polling or ad hoc waiting.
B ROWSIX provides an XMLHttpRequest-like API for
sending requests from the web application to in-browser
HTTP servers running in B ROWSIX. This allows JavaScript
to interact with HTTP 1.1 servers running as B ROWSIX
processes as if they were remote HTTP servers. The API
encapsulates the details of connecting a B ROWSIX socket
to the server, serializing the HTTP request to a byte array,sending the byte array to the B ROWSIX process, processing
the (potentially chunked) HTTP response, and generating the
expected web events.
4.2

Common Services

B ROWSIX provides a small syscall layer as a JavaScript
module that runs in a Web Worker. This layer provides a concrete API for asynchronous system calls over the browser’s
message passing primitives. Language runtimes use this module to communicate with the kernel. Methods provided by thesyscall layer take the same arguments as Linux system callsof the same name, along with an additional argument: a callback function. This callback is executed when the syscall
module receives a message response from the kernel. Unlike
a traditional single-threaded process, a B ROWSIX process
can have multiple outstanding system calls, which enables

B ROWSIX Runtime Support

Applications invoke B ROWSIX system calls indirectly throughtheir runtime systems. This section describes the runtime support we added to GopherJS, Emscripten, and Node.js alongwith the APIs exposed to web applications so they can executeprograms in B ROWSIX.

259

function sys_g etdents 64 ( cb , trap , fd , dirp , len ) {var done = function ( err , buf ) {if (! err )dirp . set ( buf ) ;cb ([ err ? -1 : buf . byteLength , 0 , err ? err :0]) ;};syscall_1 . syscall . getdents ( fd , len , done ) ;}__syscall220 : function ( which , varargs ) {# if E M T E R P R E T I F Y _ A SY N C
return E m te r p r et e rA s y nc . handle ( function ( resume ){var fd = SYSCALLS . get () , dirp = SYSCALLS . get() , count = SYSCALLS . get () ;var done = function ( err , buf ) {if ( err > 0)
HEAPU8 . subarray ( dirp , dirp + buf . byteLength) . set ( buf ) ;resume ( function () {return err ;}) ;};SYSCALLS . browsix . syscall . async ( done , ’getdents ’ , [ fd , count ]) ;}) ;# elsevar fd = SYSCALLS . get () , dirp = SYSCALLS . get () ,count = SYSCALLS . get () ;return SYSCALLS . browsix . syscall . sync (220 , fd ,dirp , count ) ;# endif},Figure 5: Implementing the getdents64 system call in
GopherJS.
runtimes like GopherJS to implement user-space threads on
top of a single Web Worker execution context.
Signals are sent over the same message passing interface
as system calls. The common syscall module provides away to register signal handlers for the standard Unix signals,
such as SIGCHLD.
4.3

Figure 6: Implementing the B ROWSIX getdents64 syscallin Emscripten.

Runtime-specific Integration

For many programming languages, existing language runtimes targeted for the browser must bridge the impedancemismatch between synchronous APIs present on Unix-likesystems and the asynchronous world of the browser. Compileto-JavaScript systems like Emscripten, ClojureScript [8],Scala.js [3], js of ocaml [14], WhaleSong (Racket) [15], andGopherJS all employ different approaches. Since B ROWSIX
supports both synchronous and asynchronous system calls,
language runtimes can choose the system call convention
most appropriate for their implementation.
This section describes the runtime support we added tolanguage runtimes for Go, C/C++, and Node.js. Extending
B ROWSIX support to additional language runtimes remains
as future work.

re-winding the stack and continuing execution. The syscall
library invokes a function specific to each supported systemcall to marshal data to and from the B ROWSIX kernel. Adding
support for any new system call is a matter of writing a small
handler function and registering it; an example is shown in
Figure 5
B ROWSIX replaces a number of low-level runtime functions; the most important are syscall.forkAndExecInChildand net.Listen. The former is overridden to directly invoke B ROWSIX’s spawn system call, and the latter to provide
access to B ROWSIX socket services. Additional integration
points include an explicit call to the exit system call whenthe main function exits, and waiting until the process’s arguments and environment have been received before starting
main() (see §3.3).

Go: Go is a systems language developed at Google designed for readability, concurrency, and efficiency. To run
Go programs under B ROWSIX, we extended the existing GopherJS compiler and runtime to support issuing and waiting for system calls under B ROWSIX. GopherJS already provides full support for Go language features like goroutines(lightweight threads), channels (communication primitives),and delayed functions.
We extended the GopherJS runtime with support for
B ROWSIX through modifications to the runtime. The main
integration points are a B ROWSIX-specific implementation of
the syscall.RawSyscall function (which handles syscalls
in Go), along with overrides of several Go runtime functions.
The replacement for RawSyscall is implemented in Go.
It allocates a Go channel object, and this function calls
into the B ROWSIX JavaScript syscall library, passing thesystem call number, arguments, and a callback to invoke.
RawSyscall then performs a blocking read on the Go channel, which suspends the current goroutine until the callback is
invoked. When the system call response is received from theB ROWSIX kernel, GopherJS’s existing runtime takes care of

C and C++: We also extend Emscripten, Mozilla Research’s LLVM-based C and C++ compiler that targets
JavaScript, with support for B ROWSIX. B ROWSIX-enhanced
Emscripten supports two modes - synchronous system calls
and asynchronous system calls (described in Section 3.2),
one of which is selected at compile time. Asynchronous
system calls require use of Emscripten’s interpreter mode(named the “Emterpreter”) to save and restore the C stack. All
functions that may be on the stack during a system call must
be interpreted to ensure the stack can be restored when thesystem call completes. Emscripten can selectively compile
other functions in an application to asm.js, which will be
JIT-compiled and run as native JavaScript by the browser.
Synchronous system calls do not have this limitation.
As with GopherJS, Emscripten provides a clear integration
point at the level of system calls. Emscripten provides implementations for a number of system calls, but is restricted toperforming in-memory operations that do not block. We re-260

place Emscripten system call implementations with ones thatcall into the B ROWSIX kernel, such as in Figure 6. In the caseof getdents and stat, padding was added to C structure
definitions to match the layout expected by the B ROWSIX
kernel.
When a C process invokes fork, the runtime sends a
copy of the global memory array, which includes the C
stack and heap, along with the current program counter(PC) to the kernel. After the kernel launches a new Web
Worker, it transfers this copy of global memory and PC to the
new Worker as part of the initialization message. When the
Emscripten runtime in the new B ROWSIX process receives theinitialization message, if a memory array and PC are present
the runtime swaps them in and invokes the Emterpreter tocontinue from where fork was invoked.

Figure 7: A meme generator built using B ROWSIX. Allserver-side functionality was moved into the browser without
modifying any code.

Node.js: Node.js (a.k.a. “Node”) is a platform for building
servers and command line tools with JavaScript, implemented
in C, C++ and JavaScript on top of the V8 JavaScript engine. Node.js APIs are JavaScript modules that are loaded
into the current JavaScript context by invoking the requirebuilt-in function. These high-level APIs are implemented inplatform-agnostic JavaScript and call into lower-level C++
bindings, which in turn invoke operating system interfaces
like filesystem IO, TCP sockets, and child process management. Node.js embraces the asynchronous, callback-oriented
nature of JavaScript – most Node APIs that perform system
calls take a callback parameter that is invoked when results
are ready.
To run servers and utilities written for Node.js under
B ROWSIX, we provide a browser-node executable thatpackages Node’s high-level APIs with pure-JavaScript replacements for Node’s C++ bindings that invoke B ROWSIX
system calls. browser-node is a single file that runs in a
B ROWSIX process. B ROWSIX also replaces several othernative modules, like the module for parsing and generating
HTTP responses and requests, with pure JavaScript implementations. Node executables can be invoked directly, suchas node server.js, or will be invoked indirectly by the
kernel if node is specified as the interpreter in the shebangline of a text file marked as executable.

5.

server-side depending on network and device characteristics.
Second, we build a Unix terminal that lets application developers use dash, a widely-used POSIX shell, to interact withB ROWSIX in a familiar manner.
5.1.1

Our meme generator lets users create memes consistingof images with (nominally) humorous overlaid text. Figure 7 contains a screenshot. Existing services, such as
MemeGenerator.net, perform meme generation server-side.
Moving meme creation into the browser would reduce server
load and reduce latency when the network is overloaded or
unreliable, but doing so would normally present a significant
engineering challenge. The meme generation server uses
sockets to communicate with the browser over HTTP andreads meme templates from the file system. Before B ROWSIX,
the client and server code would need to be re-architected
and rewritten to run together in the browser.
To demonstrate B ROWSIX’s ability to quickly port codefrom the server to the web, we implement our meme creator asa traditional client/server web application; Figure 8a contains
a system diagram. The client is implemented in HTML5 and
JavaScript, and the server is written in Go. The server reads
base images and font files from the filesystem, and uses offthe-shelf third-party Go libraries for image manipulation andfont rendering to produce memes [5]. The server also uses
Go’s built-in http module to run its web server. Note that
this server is stateless, following best practices [10]; portinga stateful server would naturally require more care.
To port the server to B ROWSIX, we follow the process
outlined in Section 2. First, we compile the Go server toa single JavaScript file using GopherJS. Then, we stage
the font and images for the BrowserFS filesystem. Finally,
we augment the client application to load the B ROWSIXJavaScript module, initialize a kernel instance, and start thememe-server.
Next, we augment the web application to dynamicallyroute meme generation requests to a server running in
B ROWSIX or to the cloud. We add a function to the ap-

Evaluation

Our evaluation answers the following questions: (1) Does
bringing Unix abstractions into the browser enable compelling use cases? (2) Is the performance impact of running
programs under B ROWSIX acceptable?
5.1

Meme Generator

Case Studies

We evaluate the applicability and advantages of bringing Unix
abstractions into the browser with two case studies in addition to the LATEX editor from the overview (§2). First, webuild a web application for creating memes that can run its
unmodified server in B ROWSIX. The meme generator transparently switches between generating memes in-browser or261

(a) Meme creator running without B ROWSIX(b) Meme creator running with B ROWSIX

Figure 8: System diagram of the meme generator application with and without B ROWSIX, demonstrating how the client andserver interact with one another. With B ROWSIX, the server runs in the browser without code modifications.
plication that implements a simple policy: if the network is
inaccessible, or the browser is running on a desktop (which isa proxy for a powerful device), the application routes meme
generation requests to the server running in B ROWSIX. Otherwise, it sends the requests to the remote server. In both cases,
the web application uses an XMLHttpRequest-like interface
to make the request, requiring little change to the existingcode.
Figure 8b displays a system diagram of the modified meme
generator. With this modification, meme generation works
even when offline. The code required to implement this policy
and dynamic behavior amounted to less than 30 lines of
JavaScript.

5.1.2

also execute Go, C/C++, and Node.js programs from the shell
as expected.
The terminal includes a variety of Unix utilities on theshell’s PATH that we wrote for Node.js: cat, cp, curl, echo,
exec, grep, head, ls, mkdir, rm, rmdir, sh, sha1sum,
sort, stat, tail, tee, touch, wc, and xargs. These programs run equivalently under Node and B ROWSIX without
any modifications, and were used heavily during development
to debug B ROWSIX functionality.
Summary: B ROWSIX makes it trivial to execute applications designed to run in a Unix environment within thebrowser, enabling the rapid development of sophisticated web
applications. These applications can incorporate server code
into the browser and harness the functionality of existing
applications.

The B ROWSIX Terminal

To make it easy for developers to interact with and test
programs in B ROWSIX, we implement an in-browser Unix
terminal that exposes a POSIX shell. The terminal uses the
Debian Almquist shell (dash), the default shell of Debian andUbuntu. We compile dash to JavaScript using B ROWSIXenhanced Emscripten, and run it in a B ROWSIX process.
Since the B ROWSIX terminal uses a standard shell, developers can use it to run existing and new shell scripts
in B ROWSIX. Developers can pipe programs together (e.g.
cat file.txt | grep apple > apples.txt), executeprograms in a subshell in the background with &, run shell
scripts, and change environment variables. Developers can

5.2

Performance

We evaluate the performance overhead of B ROWSIX on ourcase studies. All experiments were performed on a late-2013
Macbook Pro with an Intel i7-4558U CPU and 16 GB of
RAM, running Linux 4.8. Safari performance numbers arefrom the same machine running macOS Sierra.
LATEX Editor: Running pdflatex under B ROWSIX imposes an order of magnitude slowdown, as shown in Figure 9. A native execution of pdflatex under Linux takes
around 86 milliseconds on a single page document with abibliography. When using synchronous system calls (as sup-262

Platform
Linux
Chrome Beta 56
Firefox Nightly 54
Firefox Nightly 54*
Safari Tech Preview 22

Command

Runtime0.086s2.0s (24×)
2.6s (31×)
0.79s (9×)
1.8s (21×)

sha1sumls

Native0.002s0.001sNode.js
0.067s
0.044sB ROWSIX
0.189s
0.108sFigure 10: Execution time of utilities under B ROWSIX, compared to the same utilities run under Node.js, and the native GNU/Linux utilities. sha1sum is run on usr/bin/node,and ls is run on /usr/bin. Running in JavaScript (withNode.js and B ROWSIX) imposes most overhead; running in
the B ROWSIX environment adds roughly another 3× overhead.

Figure 9: Execution times for compiling a single-page document with a bibliography with pdflatex from TeX Live2015. Times reported are the mean of 10 executions. (* Indicates Firefox was built with an 8-line patch enabling asm.js
validation with the use of SharedArrayBuffers.)

B ROWSIX Terminal and Utilities: Unix utilities provide
a mechanism to compare the performance of real-world
programs under Linux and B ROWSIX. Figure 10 shows
the results of running the same JavaScript utility under
B ROWSIX and on Linux under Node.js, and compares this tothe execution time of the corresponding GNU Coreutils utility(written in C, running on Linux). Most of the overhead can be
attributed to JavaScript (the basis of Node.js and B ROWSIX);
subsequently running in the B ROWSIX environment imposesroughly a 3× overhead over Node.js on Linux. Nonetheless,execution time (completion in under 200 milliseconds) is low
enough that it should be generally acceptable to users.

ported by Chrome, Firefox, and Safari), the same documentbuilds in B ROWSIX in between 0.79 and 2.6 seconds, a slowdown of between 9× and 31×. Firefox has asm.js specificoptimizations that are enabled when a JavaScript module
passes asm.js validation. Using a SharedArrayBuffer for theasm.js module’s heap, as B ROWSIX does for synchronous
system calls, currently causes Firefox to fail validation andfall back to the standard JIT5 . The modified Firefox results
show that if the rules for asm.js are slightly relaxed to allow
SharedArrayBuffers for the heap, performance is improved byover 3×. Building pdflatex with asynchronous system calls
and the Emterpreter for broader compatibility with today’sbrowsers increases runtime to around 12 seconds.

Microbenchmarks: We ran four benchmarks from the
HBench-OS benchmark suite [2] to characterize the relative
performance of the operating system services provided by
B ROWSIX. The results are in Figure 11. The first two benchmarks, lat syscall and lat fslayer, perform simple
system calls, getpid and a single-byte write to /dev/null
respectively. These calls, which run three orders of magnitude
slower under B ROWSIX, accentuate B ROWSIX’s overhead:
the host OS must schedule several userspace threads to complete each B ROWSIX system call. In Linux, these system
calls typically do not block or cause a task reschedule. Benchmarks that perform more work in the kernel result in lower
overhead. The latter two benchmarks, lat fs and lat tcp,
respectively create a 1024-byte file and perform a pair of
single-byte read and writes over a socket on the loopback
interface between two processes. The resulting overhead is
between 99 − 125× for file creation and 10 − 24× for TCP.
In these cases, B ROWSIX’s system call overhead is amortized across useful work done in the kernel. The lat tcp
benchmark is the only benchmark that requires schedulingmultiple processes under Linux, which B ROWSIX execution
more closely matches.

Meme Generator: The meme generator performs two typesof HTTP requests to the server: requests for a list of available
background images, and requests to generate a meme. We
benchmark the performance of the meme generator server
running natively and running in Browsix in both Google
Chrome 52 and Mozilla Firefox 48. Times reported are themean of 100 runs following a 20-run warmup.
On average, a request for a list of background images
takes 1.7 milliseconds natively, 9 ms in Chrome, and 6 ms
in Firefox. While requests to a server running natively on
the same machine as the client are faster than those servedby B ROWSIX, B ROWSIX is faster once a network connection
and roundtrip latencies are factored in. When comparing an
instance of the meme-server running on an EC2 instance,
the in-B ROWSIX request completed three times as fast as therequest to the remote machine.
The in-B ROWSIX HTTP request to generate a meme
takes approximately two seconds, compared to 200 ms whenrunning server-side. We believe this slowdown is primarily
due to the lack of native 64-bit integer primitives whennumerical code is compiled to JavaScript with GopherJS
rather than overhead introduced by B ROWSIX; we expect thisto improve when future browsers support native access to 64bit integers (through WebAssembly), and with independent
improvements to the GopherJS compiler.

Summary: While B ROWSIX’s performance is limited by
the performance of underlying browser primitives (notably,
the lack of native 64-bit integers and message passing performance), it provides acceptable performance for a range ofapplications.

5 https://bugzilla.mozilla.org/show_bug.cgi?id=1334941

263

Benchmark
lat syscall:getpid
lat fslayer
lat fs:create 1024
lat tcp:localhostLinux
0.04 µs
0.06 µs
25.57 µs
16.98 µs

Chrome32.68 µs (767×)33.64 µs (548×)3204.73 µs (125×)374.09 µs(22×)

Firefox36.27 µs (851×)38.56 µs (628×)2963.42 µs (116×)415.18 µs(24×)

Safari25.48 µs (598×)26.84 µs (437×)2520.64 µs(99×)
174.16 µs(10×)

Figure 11: Results of running several HBench-OS latency benchmarks under Linux and under B ROWSIX. Numbers in parentheses
are relative slowdown compared to native. Each benchmark was run 25 times per environment and the mean is displayed. All
benchmarks used synchronous B ROWSIX system calls (Section 3.2) except for lat tcp, which requires asynchronous system
calls for fork support. Browsers tested were Chrome Beta 56, Firefox Nightly 54, and Safari Technology Preview 22.

6.

Discussion

implementation across browsers, would enable B ROWSIX to
support additional features like shared mmap and shm6 .

The process of implementing B ROWSIX has highlighted
opportunities for improvement in the implementation andspecification of browser APIs, especially Web Workers. We
outline a number of optimizations and natural extensions thatare generally useful, and would extend B ROWSIX’s reach.

Stack Management: C provides the ability to save andchange the current thread’s context with the setcontext andgetcontext functions. While rarely useful or advisable forapplications, it enables specialized low-level libraries to saveand restore the C stack. A similar JavaScript primitive coupled with the use of SharedArrayBuffers would let B ROWSIX
support fork in Emscripten applications as a synchronous
system call.

Worker Priority Control: The parent of a Web Worker
has no way to lower the priority of a created worker. As
workers are implemented on top of OS threads, this concept
maps cleanly onto OS-level priorities/niceness. Providing
this facility would let web applications prevent a low-priority
CPU-intensive worker from interfering with the main browser
thread.

7.

Related WorkIn-Browser Execution Environments: B ROWSIX significantly extends past efforts to bring traditional APIs andgeneral-purpose languages to the browser; Table 1 provides
a comparison. Doppio’s focus is providing single-process
POSIX abstractions [13]. B ROWSIX builds on and extends its
filesystem component, BrowserFS, to support multiple processes. Emscripten compiles LLVM bytecode to JavaScript,
enabling the compilation of C and C++ to JavaScript [16];as Section 4 describes, B ROWSIX augments its runtime system so that unmodified C and C++ programs compiled with
Emscripten can take full advantage of its facilities. B ROWSIX
provides similar runtime support for Go programs throughGopherJS [11].
The Illinois Browser Operating System (IBOS) makes key
browser APIs like HTTP requests and cookie storage OS
primitives, removing library and OS code not necessary for
those APIs from the trusted computing base [12]. Embassies
refactors the web browser to separate the client execution
interface from the developer programming interface [9]. Embassies models the client as a pico-datacenter, running eachtenant (web page) in a separate VM. In addition to providing
improved isolation and security for traditional web pages,
Embassies enables safely executing arbitrary native code on
the client in addition to a traditional WebKit HTML stack.
Browsix provides OS abstractions on top of browser APIs,
and could be run in IBOS or Embassies for improved isolationand security.

postMessage() Backpressure: Traditional operating systems attempt to prevent individual processes from affecting system stability in a number of ways. One of theseis providing backpressure, wherein the process attempting
to write to a pipe or socket is suspended (the system call
blocks) until the other end of the pipe reads the data or thedata fits into a fixed size buffer. This approach prevents unbounded resource allocation in the kernel. In the browser, thepostMessage() function can be called from a JavaScript
context an unbounded number of times and can eventuallycause the browser to run out of allocatable memory.
Message Passing Performance: Message passing is threeorders of magnitude slower than traditional system calls in
the three browsers we evaluate, Chrome, Firefox, and Safari.
A more efficient message passing implementation would
improve the performance of B ROWSIX’s system calls andother inter-process communication.
Memory Mapping: B ROWSIX is currently unable to support C/C++ applications like PostgreSQL that use mmap. Emscripten uses a single typed array to represent the unmanaged
C/C++ heap. While recent browser interfaces make it possible to share this typed array among B ROWSIX processes [6],browsers cannot yet map regions of the typed array into another typed array, which would be necessary to fully emulate
mmap. Features on the WebAssembly roadmap, which aim for

6 https://github.com/WebAssembly/design/blob/master/

FutureFeatures.md

264

†

†

3
3

3
3

3
3

ls

3

3

3
3

3
3

3
3

na

3

es

S ig

†

P ip

3

s

t se
cke
So

3
†

sse

rve
rs

n ts
tc
cke
So

3
†

Pr
oce

L ANGUAGE RUNTIMESB ROWSIX
D OPPIO [13]asm.js
WebAssembly
Emscripten (C/C++)
GopherJS (Go)B ROWSIX + Emscripten
B ROWSIX + GopherJS

lie

em
y st
es
F il

E NVIRONMENTS

Table 1: Feature comparison of JavaScript execution environments and language runtimes for programs compiled to JavaScript.
† indicates that the feature is only accessible by a single running process. B ROWSIX provides multi-process support for all of
its features. Both asm.js and WebAssembly are pure computational environments and as such don’t provide any of the OSfeatures listed.
and helpful comments. We also thank Romāns Volosatovs
and Google for supporting him as part of the Google Summerof Code.

Xax is a browser plugin model designed to ease porting
legacy code to the web [4]. It shares a similar focus on OS
independence and legacy support along with an asynchronous
system-call ABI, but runs native code in a hardware-isolated
picoprocess. The Xax model requires developers to compile
and host binaries for all architectures an end user mightuse, while B ROWSIX leverages the cross-platform nature of
JavaScript and WebAssembly to enable a compile-once, runeverywhere development workflow.

References[1] A. Baumann, P. Barham, P.-E. Dagand, T. Harris, R. Isaacs,
S. Peter, T. Roscoe, A. Schüpbach, and A. Singhania. The
multikernel: a new OS architecture for scalable multicore
systems. In Proceedings of the ACM SIGOPS 22nd symposium
on Operating systems principles, pages 29–44. ACM, 2009.

Kernel Design and OS Interfaces: B ROWSIX resembles aLinux kernel task running on a microkernel [7], as it relies onan underlying system for messaging, scheduling and context
switching. Barrelfish, a many-core, heterogenous OS [1]showed that asynchronous, shared-nothing system calls could
be practical. B ROWSIX somewhat mirrors the per-core, sharednothing structure of a multikernel, as individual B ROWSIX
processes do not use inter-domain communication for tasks
like memory allocation and timers.

8.

[2] A. B. Brown and M. I. Seltzer. Operating system benchmarking in the wake of lmbench: A case study of the performanceof netbsd on the intel x86 architecture. In Proceedings of the1997 ACM SIGMETRICS International Conference on Measurement and Modeling of Computer Systems, SIGMETRICS’97, pages 214–224, New York, NY, USA, 1997. ACM.
[3] S. Doeraene. Scala.js: Type-Directed Interoperability with
Dynamically Typed Languages. Technical report, École polytechnique fédérale de Lausanne, 2013.

Conclusion[4] J. R. Douceur, J. Elson, J. Howell, and J. R. Lorch. Leveraging
legacy code to deploy desktop applications on the web. In
Proceedings of the 8th USENIX Conference on Operating
Systems Design and Implementation, OSDI’08, pages 339–
354, Berkeley, CA, USA, 2008. USENIX Association.

This paper introduces B ROWSIX, a framework that brings theessence of Unix to the browser. B ROWSIX makes it almost
trivial to build complex web applications from components
written in a variety of languages without modifying any code,and promises to significantly reduce the effort required tobuild highly sophisticated web applications. B ROWSIX is
open source, and is freely available at https://browsix.
org.

[5] M. Fogleman. fogleman/gg: Go Graphics - 2D rendering in Gowith a simple API, 2016. https://github.com/fogleman/gg.
[6] L. T. Hansen and J. Fairbank. ECMAScript Shared Memory
and Atomics, 2016. https://tc39.github.io/ecmascript_
sharedmem/shmem.html.

Acknowledgments[7] H. Härtig, M. Hohmuth, J. Liedtke, J. Wolter, and S. Schönberg.
The performance of µ-kernel-based systems. In Proceedingsof the Sixteenth ACM Symposium on Operating Systems Principles, SOSP ’97, pages 66–77, New York, NY, USA, 1997.
ACM.

This material is based upon work supported by the National
Science Foundation under Grant No. CNS-1525888. John
Vilk was supported by a Facebook Graduate Fellowship. The
authors thank our anonymous reviewers for their feedback265[8] R. Hickey. Clojurescript. http://clojurescript.org/
about/rationale, 2016.

[13] J. Vilk and E. D. Berger. D OPPIO: Breaking the browser language barrier. In Proceedings of the 2014 ACM SIGPLAN
Conference on Programming Language Design and Implementation (PLDI 2014), pages 508–518. ACM, 2014.

[9] J. Howell, B. Parno, and J. R. Douceur. Embassies: Radicallyrefactoring the web. In Proceedings of the 10th USENIX
Conference on Networked Systems Design and Implementation,
nsdi’13, pages 529–546, Berkeley, CA, USA, 2013. USENIX
Association.

[14] J. Vouillon and V. Balat. From bytecode to JavaScript: theJs of ocaml compiler. Software: Practice and Experience,
44(8):951–972, 2014.

[10] T. Mauro. Adopting Microservices at Netflix: Lessons forArchitectural Design, 2015.

[15] D. Yoo and S. Krishnamurthi. Whalesong: running racket in
the browser. In DLS’13, Proceedings of the 9th Symposium on
Dynamic Languages, part of SPLASH 2013, Indianapolis, IN,
USA, October 26-31, 2013, pages 97–108, 2013.

https://www.nginx.com/blog/microservices-atnetflix-architectural-best-practices/.

[16] A. Zakai. Emscripten: an LLVM-to-JavaScript compiler. In
OOPSLA Companion, pages 301–312, 2011.

[11] R. Musiol. gopherjs/gopherjs: A compiler from Go to
JavaScript for running Go code in a browser, 2016. https://github.com/gopherjs/gopherjs.
[12] S. Tang, H. Mai, and S. T. King. Trust and protection in
the illinois browser operating system. In Proceedings of the
9th USENIX Conference on Operating Systems Design and
Implementation, OSDI’10, pages 17–31, Berkeley, CA, USA,2010. USENIX Association.

266