https://github.com/second-state/ssvm-napi-extensions
https://github.com/second-state/ssvm-napi-extensions
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/second-state/ssvm-napi-extensions
- Owner: second-state
- License: apache-2.0
- Created: 2020-11-24T08:22:02.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2021-09-12T08:26:42.000Z (over 4 years ago)
- Last Synced: 2025-03-30T08:33:15.739Z (about 1 year ago)
- Language: C++
- Size: 169 KB
- Stars: 4
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Second State WebAssembly VM for Node.js Addon with all extensions
The [Second State VM (SSVM)](https://github.com/second-state/ssvm) is a high-performance WebAssembly runtime optimized for server-side applications. This project provides support for accessing SSVM as a Node.js addon. It allows Node.js applications to call WebAssembly functions written in Rust or other high-performance languages. [Why do you want to run WebAssembly on the server-side?](https://cloud.secondstate.io/server-side-webassembly/why) The SSVM addon could interact with the wasm files generated by the [ssvmup](https://github.com/second-state/ssvmup) compiler tool.
## NOTICE
SSVM Node.js Addon is in active development.
In the current stage, our prebuilt version **only supports** x86\_64 Linux.
Or you could use `--build-from-source` flag to build from source during addon installation.
## Requirements
After SSVM Napi 0.4.0 release, we upgrade the base image from `Ubuntu 18.04` to `Ubuntu 20.04`.
Users should install the dependencies by the following requirments:
* boost >= 1.65.0
* llvm >= 10
* liblld-10-dev >= 10
* libstdc++6 >= 6.0.28 (GLIBCXX >= 3.4.28)
* g++ version >= 9.0 (Optional, if you have to build from source)
For the tensorflow extensions:
* libpng-dev
* libjpeg-dev
* libtensorflow.so
* Please refer to the TensorFlow website for more details
```base
wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-2.4.0.tar.gz \
&& tar -C /usr/local -xzf libtensorflow-cpu-linux-x86_64-2.4.0.tar.gz \
&& ldconfig
```
* libtensorflowlite\_c.so
* You can use the following commands to get libtensorflowlite\_c.so
```bash
# Download TensorFlow deps
wget https://github.com/second-state/ssvm-tensorflow-deps/releases/download/0.1.0/ssvm-tensorflow-deps-lite-0.1.0-linux-x64.tar.gz
tar -zxvf ssvm-tensorflow-deps-lite-0.1.0-linux-x64.tar.gz
cp ./libtensorflowlite_c.so /usr/local/lib
```
## Prepare environment
### Use our docker image or dockerfile
```bash
$ docker pull secondstate/ssvm-extensions
# Or you can build it on your local environment.
$ docker build . -f utils/docker/Dockerfile -t secondstate/ssvm-extensions
```
### Verify the version of llvm
```bash
$ sudo apt list | grep llvm
...omitted...
llvm-dev/focal,now 1:10.0-50~exp1 amd64 [installed]
llvm-runtime/focal,now 1:10.0-50~exp1 amd64 [installed,automatic]
llvm/focal,now 1:10.0-50~exp1 amd64 [installed,automatic]
...omitted...
# If the version is 1:10.x, then your llvm version is correct.
```
### Verify the version of libstdc++6
```bash
$ strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX
...omitted...
GLIBCXX_3.4.24
GLIBCXX_3.4.25
GLIBCXX_3.4.26
GLIBCXX_3.4.27
GLIBCXX_3.4.28
GLIBCXX_DEBUG_MESSAGE_LENGTH
# If you can find GLIBCXX_3.4.28 in the output, then your libstdc++6 version is correct.
```
### Works with Rust library using Wasm-Bindgen
Please refer to [Tutorial: A Wasm-Bindgen application](./Tutorial_Wasm_Bindgen.md).
### Works with Rust application using standalone wasm32-wasi backend
Please refer to [Tutorial: A standalone wasm32-wasi application](./Tutorial_Wasm32_Wasi.md).
## APIs
### Constructor: `ssvm.VM(wasm, ssvm_options) -> vm_instance`
* Create a ssvm instance by given wasm file and options.
* Arguments:
* `wasm`: Input wasm file, can be the following two formats:
1. Wasm file path (String, e.g. `/tmp/hello.wasm`)
2. Wasm bytecode format which is the content of a wasm binary file (Uint8Array)
* `options`: An options object for setup the SSVM execution environment.
* `options`
* `args` : An array of strings that Wasm application will get as function arguments. Default: `[]`.
* `env` : An object like `process.env` that Wasm application will get as its environment variables. Default: `{}`.
* `preopens` : An object which maps ':'. E.g. `{'/sandbox': '/some/real/path/that/wasm/can/access'}` Default: `{}`.
* `EnableWasiStartFunction` : This option will disable wasm-bindgen mode and prepare the working environment for standalone wasm program. If you want to run an appliation with `main()`, you should set this to `true`. Default: `false`.
* `EnableAOT` : This option will enable ssvm aot mode. Default: `false`.
* `EnableMeasurement` : This option will enable measurement but decrease its performance. Default: `false`.
* `AllowCommands` : An array of strings that indicate what commands are allowed to execute in the SSVM Process Module. Default `[]`.
* `AllowAllCommands` : Allow users to call any command in the SSVM Process Module. This option will overwrite the `AllowCommands`. Default: `false`.
* Return value:
* `vm_instance`: A ssvm instance.
### Methods
#### `Start() -> Integer`
* Emit `_start()` and expect the return value type is `Integer` which represents the error code from `main()`.
* Arguments:
* If you want to append arguments for the standalone wasm program, please set the `args` in `wasi options`.
* Example:
```javascript
let error_code = Start();
```
#### `Run(function_name, args...) -> void`
* Emit `function_name` with `args` and expect the return value type is `void`.
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
Run("Print", 1234);
```
#### `RunInt(function_name, args...) -> Integer`
* Emit `function_name` with `args` and expect the return value type is `Integer` (Int32).
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
```
#### `RunUInt(function_name, args...) -> Integer`
* Emit `function_name` with `args` and expect the return value type is `Integer` (UInt32).
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
```
#### `RunInt64(function_name, args...) -> BigInt`
* Emit `function_name` with `args` and expect the return value type is `BigInt` (Int64).
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
```
#### `RunUInt64(function_name, args...) -> BigInt`
* Emit `function_name` with `args` and expect the return value type is `BigInt` (UInt64).
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
```
#### `RunString(function_name, args...) -> String`
* Emit `function_name` with `args` and expect the return value type is `String`.
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunString("PrintMathScore", "Amy", 98);
// result: "Amy’s math score is 98".
```
#### `RunUint8Array(function_name, args...) -> Uint8Array`
* Emit `function_name` with `args` and expect the return value type is `Uint8Array`.
* Arguments:
* `function_name` : The function name which users want to emit.
* `args` \*: The function arguments. The delimiter is `,`
* Example:
```javascript
let result = RunUint8Array("Hash", "Hello, world!");
// result: "[12, 22, 33, 42, 51]".
```
#### `Compile(output_filename) -> boolean`
* Compile a given wasm file (can be a file path or a byte array) into a native binary whose name is the given `output_filename`.
* This function uses SSVM AOT compiler.
* Return `false` when the compilation failed.
```javascript
// Compile only
let vm = ssvm.VM("/path/to/wasm/file", options);
vm.Compile("/path/to/aot/file");
// When you want to run the compiled file
let vm = ssvm.VM("/path/to/aot/file", options);
vm.RunXXX("Func", args);
```
#### `GetStatistics() -> Object`
* If you want to enable measurement, set the option `EnableMeasurement` to `true`. But please notice that enabling measurement will significantly affect performance.
* Get the statistics of execution runtime.
* Return Value `Statistics`
* `Measure` -> : To show if the measurement is enabled or not.
* `TotalExecutionTime` -> : Total execution time (Wasm exeuction time + Host function execution time) in `ns` unit.
* `WasmExecutionTime` -> : Wasm instructions execution time in `ns` unit.
* `HostFunctionExecutionTime` -> : Host functions (e.g. eei or wasi functions) execution time in `ns` unit.
* `InstructionCount` -> : The number of executed instructions in this execution.
* `TotalGasCost` -> : The cost of this execution.
* `InstructionPerSecond` -> : The instructions per second of this execution.
```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
let stat = GetStatistics();
/*
If the `EnableMeasurement: true`:
stat = Statistics: {
Measure: true,
TotalExecutionTime: 1512,
WasmExecutionTime: 1481,
HostFunctionExecutionTime: 31,
InstructionCount: 27972,
TotalGasCost: 27972,
InstructionPerSecond: 18887238.35246455
}
Else:
stat = Statistics: {
Measure: false
}
*/
```