php-wasm/php-wasm

Run WebAssembly binaries safely with the `wasmer-php` extension.

0.5.0 2019-07-16 07:42 UTC

README

A complete and mature WebAssembly runtime for PHP based on Wasmer.

Features:

  • Easy to use: The wasmer API mimics the standard WebAssembly API,
  • Fast: wasmer executes the WebAssembly modules as fast as possible, close to native speed,
  • Safe: All calls to WebAssembly will be fast, but more importantly, completely safe and sandboxed.

Example

There is a toy program in examples/simple.rs, written in Rust (or any other language that compiles to WebAssembly):

#[no_mangle]
pub extern fn sum(x: i32, y: i32) -> i32 {
    x + y
}

After compilation to WebAssembly, the examples/simple.wasm binary file is generated. (Download it).

Then, we can execute it in PHP (!) with the examples/simple.php file:

$instance = new Wasm\Instance(__DIR__ . '/simple.wasm');

var_dump(
    $instance->sum(5, 37) // 42!
);

And then, finally, enjoy by running:

$ php -d extension=wasm examples/simple.php
int(42)

Usage

This repository contains basically two things:

  1. The wasmer-php extension, and
  2. The Wasm library.

The wasmer-php extension provides a raw API around WebAssembly. The Wasm library is a layer on top of wasmer-php to provide more safety and a more user-friendly API.

See the API documentations with examples.

To compile the entire project, run the following commands:

$ just build
$ php -d extension=wasm examples/simple.php

If the provided shared libraries are not compatible with your system, please try running just build-runtime first.

(Yes, you need just).

Testing

Once the extension is compiled and installed (just run just rust && just php), run the following commands:

$ composer install
$ composer test

What is WebAssembly?

Quoting the WebAssembly site:

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

About speed:

WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.

About safety:

WebAssembly describes a memory-safe, sandboxed execution environment […].

Goals

This extension has some goals in minds. Let's list some of them:

Write PHP extensions

Taking the example of an image manipulation library, like face detection, one can use an existing Rust or C++ library, then compile it to a WebAssembly binary, and use it directly in PHP through the wasmer-php extension.

Writing a C extension for PHP with the Zend API is no longer necessary.

Cross-platform distribution and packaging (feat. Composer)

Because WebAssembly is a portable target, i.e. binaries are platform agnostics, once a library has been compiled to a WebAssembly binary, it is immediately distributable on all platforms where PHP runs. There is no compilation steps required. And to be clear, compiling a library to a WebAssembly binary does not required any PHP headers.

To push the logic further, a library compiled as a WebAssembly binary can be packaged with Composer (the PHP dependency manager), along with some PHP code to ease the manipulation of the compiled library.

Distributing a new version of a WebAssembly binary simply reduces to distributing a new file. Composer can also add constraints over the available extensions with their versions (see ext-name). All packaging scenarios are handled.

As fast as possible

We are working on being as fast as native code (see this blog post to learn more). So far, the extension provides a faster execution than PHP itself. With the nbody benchmark, the wasmer-php is 9.5 times faster than pure PHP:

subject mean mode best rstdev
wasm_extension 2,009.335μs 1,991.778μs 1,968.595μs 2.17%
pure_php 19,714.738μs 19,143.083μs 18,853.399μs 3.58%

Safety first

WebAssembly brings safety guarantees, notably due to its memory model and its sandboxed execution environment. If Rust is used as the source of a WebAssembly binary, then more safety is brought in the game. In any case, without real numbers or studies, we imagine that it is safer to use a WebAssembly binary extension rather than writing C code.

A WebAssembly binary has no access to the PHP environment (so no access to its memory or functions). It is executed in a sandbox. A WebAssembly binary is totally blind regarding the host/the system where it runs: Whether it runs in a Web browser, a server, or a PHP process, this is the same.

License

The entire project is under the MIT License. Please read the LICENSE file.