ssvm
v0.7.3
Published
Second State WebAssembly VM for Node.js Addon
Downloads
9
Readme
Second State WebAssembly VM for Node.js Addon
The Second State VM (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? The SSVM addon could interact with the wasm files generated by the ssvmup compiler tool.
NOTICE
SSVM Node.js Addon is in active development.
In the current stage, our prebuilt version only supports x86_64 and aarch64 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)
Prepare environment
Use our docker image (recommended)
$ docker pull secondstate/ssvm
For ubuntu 20.04
# Tools and libraries
$ sudo apt install -y \
software-properties-common \
cmake \
libboost-all-dev
# And you will need to install llvm for ssvm-aot tools
$ sudo apt install -y \
llvm-dev \
liblld-10-dev
# SSVM supports both clang++ and g++ compilers
# You can choose one of them for building this project
$ sudo apt install -y gcc g++
$ sudo apt install -y clang
Verify the version of llvm
$ 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
$ 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.
Works with Rust application using standalone wasm32-wasi backend
Please refer to Tutorial: A standalone wasm32-wasi application.
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 three formats:- Wasm file path (String, e.g.
/tmp/hello.wasm
) - Wasm bytecode format which is the content of a wasm binary file (Uint8Array)
- Wasm file path (String, e.g.
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 likeprocess.env
that Wasm application will get as its environment variables. Default:{}
.preopens
: An object which maps '<guest_path>:<host_path>'. 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 withmain()
, you should set this totrue
. 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 theAllowCommands
. Default:false
.
- Return value:
vm_instance
: A ssvm instance.
Methods
Start() -> Integer
- Emit
_start()
and expect the return value type isInteger
which represents the error code frommain()
. - Arguments:
- If you want to append arguments for the standalone wasm program, please set the
args
inwasi options
.
- If you want to append arguments for the standalone wasm program, please set the
- Example:
let error_code = Start();
Run(function_name, args...) -> void
- Emit
function_name
withargs
and expect the return value type isvoid
. - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
Run("Print", 1234);
RunInt(function_name, args...) -> Integer
- Emit
function_name
withargs
and expect the return value type isInteger
(Int32). - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
let result = RunInt("Add", 1, 2);
// result should be 3
RunUInt(function_name, args...) -> Integer
- Emit
function_name
withargs
and expect the return value type isInteger
(UInt32). - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
let result = RunInt("Add", 1, 2);
// result should be 3
RunInt64(function_name, args...) -> BigInt
- Emit
function_name
withargs
and expect the return value type isBigInt
(Int64). - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
let result = RunInt("Add", 1, 2);
// result should be 3
RunUInt64(function_name, args...) -> BigInt
- Emit
function_name
withargs
and expect the return value type isBigInt
(UInt64). - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
let result = RunInt("Add", 1, 2);
// result should be 3
RunString(function_name, args...) -> String
- Emit
function_name
withargs
and expect the return value type isString
. - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
let result = RunString("PrintMathScore", "Amy", 98);
// result: "Amy’s math score is 98".
RunUint8Array(function_name, args...) -> Uint8Array
- Emit
function_name
withargs
and expect the return value type isUint8Array
. - Arguments:
function_name
: The function name which users want to emit.args
<Integer/String/Uint8Array>*: The function arguments. The delimiter is,
- Example:
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.
// 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
totrue
. 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 `` unit.WasmExecutionTime
-> : Wasm instructions execution time inns
unit.HostFunctionExecutionTime
-> : Host functions (e.g. eei or wasi functions) execution time inns
unit.InstructionCount
-> : The number of executed instructions in this execution.TotalGasCost
-> : The cost of this execution.InstructionPerSecond
-> : The instructions per second of this execution.
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
}
*/