wasmerio/wasmer-postgres(新しいタブで開きます)
主要言語: Rust
💽🕸 Postgres library to run WebAssembly binaries.
- star 数
- 430
- watcher 数
- 17
- fork 数
- 16
- issue 数
- 3
- 最終更新
- 2020/12/10
主要言語: Rust
💽🕸 Postgres library to run WebAssembly binaries.
A complete and mature WebAssembly runtime for Postgres based on Wasmer. It's an original way to extend your favorite database capabilities.
Features:
wasmer API mimics the standard WebAssembly API,wasmer executes the WebAssembly modules as fast as
possible, close to native speed,Note: The project is still in heavy development. This is a 0.1.0 version. Some API are missing and are under implementation. But it's fun to play with it.
The project comes in two parts:
To compile the former, run just build (Postgres server headers are
required, see pg_config --includedir-server). To install the latter,
run just install. After that, run CREATE EXTENSION wasm in a
Postgres shell. A new function will appear: wasm_init; it must be
called with the absolute path to the shared library. It looks like
this:
$ # Build the shared library. $ just build $ # Install the extension in the Postgres tree. $ just install $ # Activate and initialize the extension. $ just host=$host database=$database activate
And you are ready to go!
Note: On macOS, the shared library extension is .dylib, on Windows,
it is .dll, and on other distributions, it is .so.
Note 2: Yes, you need just.
So far, the extension works on Postgres 10 only. It doesn't work with Postgres 11 yet (follow this issue if you want to learn more). Any help is welcomed!
Consider the examples/simple.rs program:
#[no_mangle] pub extern fn sum(x: i32, y: i32) -> i32 { x + y }
Once compiled to WebAssembly, one obtains a similar WebAssembly binary
to examples/simple.wasm (download it). To
use the sum exported function, first, create a new instance of the
WebAssembly module, and second, call the sum function.
To instantiate a WebAssembly module, the wasm_new_instance function
must be used. It has two arguments:
For instance, calling
wasm_new_instance('/path/to/simple.wasm', 'ns') will create the
ns_sum function that is a direct call to the sum exported function
of the WebAssembly instance. Thus:
-- New instance of the `simple.wasm` WebAssembly module. SELECT wasm_new_instance('/absolute/path/to/simple.wasm', 'ns'); -- Call a WebAssembly exported function! SELECT ns_sum(1, 2); -- ns_sum -- -------- -- 3 -- (1 row)
Isn't it awesome? Calling Rust from Postgres through WebAssembly!
Let's inspect a little bit further the ns_sum function:
\x \df+ ns_sum Schema | public Name | ns_sum Result data type | integer Argument data types | integer, integer Type | normal Volatility | volatile Parallel | unsafe Owner | … Security | invoker Access privileges | Language | plpgsql Source code | … Description |
The Postgres ns_sum signature is (integer, integer) -> integer,
which maps the Rust sum signature (i32, i32) -> i32.
So far, only the WebAssembly types i32, i64 and v128 are
supported; they respectively map to integer, bigint and decimal
in Postgres. Floats are partly implemented for the moment.
The extension provides two foreign data wrappers, gathered together in
the wasm foreign schema:
wasm.instances is a table with the id and wasm_file columns,
respectively for the instance ID, and the path of the WebAssembly
module,wasm.exported_functions is a table with the instance_id,
name, inputs and output columns, respectively for the
instance ID of the exported function, its name, its input types
(already formatted for Postgres), and its output types (already
formatted for Postgres).Let's see:
-- Select all WebAssembly instances. SELECT * FROM wasm.instances; -- id | wasm_file -- --------------------------------------+------------------------------- -- 426e17af-c32f-5027-ad73-239e5450dd91 | /absolute/path/to/simple.wasm -- (1 row) -- Select all exported functions for a specific instance. SELECT name, inputs, outputs FROM wasm.exported_functions WHERE instance_id = '426e17af-c32f-5027-ad73-239e5450dd91'; -- name | inputs | outputs -- --------+-----------------+--------- -- ns_sum | integer,integer | integer -- (1 row)
Benchmarks are useless most of the time, but it shows that WebAssembly can be a credible alternative to procedural languages such as PL/pgSQL. Please, don't take those numbers for granted, it can change at any time, but it shows promising results:
| Benchmark | Runtime | Time (ms) | Ratio |
|---|---|---|---|
| Fibonacci (n = 50) | postgres-ext-wasm |
0.206 | 1× |
| PL/pgSQL | 0.431 | 2× | |
| Fibonacci (n = 500) | postgres-ext-wasm |
0.217 | 1× |
| PL/pgSQL | 2.189 | 10× | |
| Fibonacci (n = 5000) | postgres-ext-wasm |
0.257 | 1× |
| PL/pgSQL | 18.643 | 73× |
Once the library is built, run the following commands:
$ just pg-start
$ just testThe entire project is under the MIT License. Please read the LICENSE file.