github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/site/content/languages/_index.md (about)

     1  +++
     2  title = "Languages"
     3  layout = "single"
     4  +++
     5  
     6  WebAssembly has a virtual machine architecture where the host is the embedding
     7  process and the guest is a program compiled into the WebAssembly Binary Format,
     8  also known as Wasm. The first step is to take a source file and compile it into
     9  the Wasm bytecode.
    10  
    11  e.g. If your source is in Go, you might compile it with TinyGo.
    12  ```goat
    13      .-----------.    .----------------------.      .-----------.
    14     /  main.go  /---->|  tinygo -target=wasi +---->/ main.wasm /
    15    '-----+-----'      '----------------------'    '-----------'
    16  ```
    17  
    18  Below are notes wazero contributed so far, in alphabetical order by language.
    19  
    20  * [Go]({{< relref "/go.md" >}}) e.g. `GOOS=js GOARCH=wasm go build -o X.wasm X.go`
    21  * [TinyGo]({{< relref "/tinygo.md" >}}) e.g. `tinygo build -o X.wasm -target=wasi X.go`
    22  * [Rust]({{< relref "/rust.md" >}}) e.g. `rustc -o X.wasm --target wasm32-wasi X.rs`
    23  * [Zig]({{< relref "/zig.md" >}}) e.g. `zig build-exe X.zig -target wasm32-wasi`
    24  
    25  wazero is a runtime that embeds in Go applications, not a web browser. As
    26  such, these notes bias towards backend use of WebAssembly, not browser use.
    27  
    28  Disclaimer: These are not official documentation, nor represent the teams who
    29  maintain language compilers. If you see any errors, please help [maintain][1]
    30  these and [star our GitHub repository][2] if they are helpful. Together, we can
    31  make WebAssembly easier on the next person.
    32  
    33  ## Constraints
    34  
    35  The [WebAssembly Core specification]({{< ref "/specs#core" >}}) defines a
    36  stack-based virtual machine. The only features that work by default are
    37  computational in nature, and the only way to communicate is via functions,
    38  memory or global variables.
    39  
    40  WebAssembly has no standard library or system call interface to implement
    41  features the operating system would otherwise provide. Certain capabilities,
    42  such as forking a process, will not work. Support of common I/O features, such
    43  as writing to the console, vary. See [System Calls](#system-calls) for more.
    44  
    45  Software is more than technical constraints. WebAssembly remains a relatively
    46  niche target, with limited maintenance and development. This means that certain
    47  features may not work, yet, even if they could technically.
    48  
    49  In general, developing with WebAssembly is difficult, and fewer problems can
    50  be discovered at compilation time vs more supported targets. This results in
    51  more runtime errors, or even panics. Where error messages exist, they may be
    52  misleading. Finally, the languages maintainers may be less familiar with how to
    53  solve the problems, and/or rely on less available key maintainers.
    54  
    55  ### Mitigating Constraints
    56  
    57  The above constraints affect the library design and dependency choices in your
    58  source, and by extension the choices of library dependencies you can use. In
    59  extreme cases, constraints or support concerns may lead developers to choose
    60  newer languages like [Zig][10].
    61  
    62  Regardless of the programming language used, the best advice is to unit test
    63  your code, and run tests with your intended WebAssembly runtime, like wazero.
    64  
    65  These tests should cover the critical paths of your code, including errors.
    66  Doing so protects your time. You'll have higher confidence, and more efficient
    67  means to communicate problems vs ad-hoc reports.
    68  
    69  ## System Calls
    70  
    71  WebAssembly is a stack-based virtual machine specification, so operates at a
    72  lower level than an operating system. For functionality the operating system
    73  would otherwise provide, system interfaces are needed.
    74  
    75  Programming languages usually include a standard library, with features that
    76  require I/O, such as writing to the console. Portability is helped along with
    77  [POSIX][3] conforming implementations of system calls, such as `fd_read`.
    78  
    79  There is a [WebAssembly System Interface]({{< ref "/specs#wasi" >}}), a.k.a.
    80  WASI, which defines host functions loosely based on POSIX. There's also a
    81  de facto implementation [wasi-libc][4]. However, WASI is not a standard and
    82  language compilers don't always support it.
    83  
    84  For example, AssemblyScript once supported WASI, but no longer does. Even
    85  compilers that target WASI using [wasi-libc][4] have gaps. For example,
    86  [TinyGo]({{< relref "/tinygo.md" >}}) does not yet support `fd_readdir`. Some toolchains have a
    87  hybrid approach. For example, Emscripten uses WASI for console output, but its
    88  own virtual filesystem functions. Finally, the team behind WASI are
    89  developing an incompatible, modular replacement to the current version.
    90  
    91  It is important to note that even when system interfaces are supported, some
    92  users prefer a freestanding compilation target that restricts them. This helps
    93  them control binary size and performance.
    94  
    95  In summary, system interfaces in WebAssembly are not standard and are immature.
    96  Developers need to understand and test the system interfaces they rely on.
    97  Testing ensures not only the present capabilities, but also they continue to
    98  operate as the ecosystem matures.
    99  
   100  ## Concurrency
   101  
   102  WebAssembly does not yet support true parallelism; it lacks support for
   103  multiple threads, atomics, and memory barriers. (It may someday; See
   104  the [threads proposal][5].)
   105  
   106  For example, a compiler targeting [WASI]({{< ref "/specs#wasi" >}}), generates
   107  a `_start` function corresponding to `main` in the original source code. When
   108  the WebAssembly runtime calls `_start`, it remains on the same thread of
   109  execution until that function completes.
   110  
   111  Concretely, if using wazero, a Wasm function call remains on the calling
   112  goroutine until it completes.
   113  
   114  In summary, while true that host functions can do anything, including launch
   115  processes, Wasm binaries compliant with the [WebAssembly Core Specification]
   116  ({{< ref "/specs#core" >}}) cannot do anything in parallel, unless they use
   117  non-standard instructions or conventions not yet defined by the specification.
   118  
   119  ### Compiling Parallel Code to Serial Wasm
   120  
   121  Until this [changes][5], language compilers cannot generate Wasm that can
   122  control scheduling within a function or safely modify memory in parallel.
   123  In other words, one function cannot do anything in parallel.
   124  
   125  This impacts how programming language primitives translate to Wasm:
   126  
   127  * Garbage collection invokes on the runtime host's calling thread instead of
   128    in the background.
   129  * Language-defined threads or co-routines fail compilation or are limited to
   130    sequential processing.
   131  * Locks and barriers fail compilation or are implemented unsafely.
   132  * Async functions including I/O execute sequentially.
   133  
   134  Language compilers often used shared infrastructure, such as [LLVM][6] and
   135  [Binaryen][7]. One tool that helps in translation is Binaryen's [Asyncify][8],
   136  which lets a language support synchronous operations in an async manner.
   137  
   138  ### Concurrency via Orchestration
   139  
   140  To work around lack of concurrency at the WebAssembly Core abstraction, tools
   141  often orchestrate pools of workers, and ensure a module in that pool is only
   142  used sequentially.
   143  
   144  For example, [waPC][9] provides a WASM module pool, so host callbacks can be
   145  invoked in parallel, despite not being able to share memory.
   146  
   147  [1]: https://github.com/bananabytelabs/wazero/tree/main/site/content/languages
   148  [2]: https://github.com/bananabytelabs/wazero/stargazers
   149  [3]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/contents.html
   150  [4]: https://github.com/WebAssembly/wasi-libc
   151  [5]: https://github.com/WebAssembly/threads
   152  [6]: https://llvm.org
   153  [7]: https://github.com/WebAssembly/binaryen
   154  [8]: https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp
   155  [9]: https://github.com/wapc/wapc-go
   156  [10]: https://ziglang.org/