• Stars
    star
    292
  • Rank 142,152 (Top 3 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 1 year ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Wasm platform for nvim.

πŸ”₯WASM_NVIM⚑

Aim:

Write a library to interface between Lua, and wasm, for enabling communication between plugins and the Neovim apis. The library language is Rust, as it is to be dynamically loaded via lua, using the neovim api, instead of going via the rpc route which creates a networking bottleneck between two or more different process, this route allows for a single process (NEOVIM) , while also a plugin ecosystem that allows any programming language that can compile to wasm.

Performance:

  • The first test is a poor mans performance test implementation, that imitates Bram's implementation of just summing a number inside a for loop, wasm is faster by 99%, due to compiler optimizations of the language om this case it is zig, this mostly shows the compilation optmization benefits that compiling to wasm could bring to the table vs JIT with LuaJIT.

  • The second one is a test where we try get the prime numbers between 0-10000, and count the number of times it could be achieved within 5 seconds, there is no constants, so even the wasm compiled shouldn't optimize the away almost all the operations like it did in the first test. Here wasm was 99% faster than Luajit. I didn't want to optmize the algorithm for each specific language, instead used basic structures, and avoid bitwise manipulation or stack pre allocation even on the zig/wasm side.

  • This image shows the tests:1690628636000

  • To run this test simply run the bellow:

    cargo make perf

    Requires:

  • Overall Wasm should be faster than luajit on average, without trying any fancy optimization techniques, for a wider range of luajit vs wasm comparisons one can check here

NOTE: Current perf test results shown are from a Windows 10 PC. That's the machine I have.

READING:

Theory

We would need an allocation and deallocation function implementation on every wasm module, that the developers of it would need to create for themselves as data between the host (this rust library) and the wasm plugin can only currently be shared using i32 or f32, directly, but other objects like buffers, structs, etc, need more than just 32bits therefore we communicate using pointers to memory to the module to access and manipulate the data from the host side, where applicable, and normally this involves json.

Installing and Setting up from release packages

-- for downloading shared librar from releases do this
-- if you don't want to build from source and just get
-- going. Warning, only supports, windows, linux, and macos
require("wasm_nvim_dl").download("windows")
-- Replace "windows" with either "linux", or "macos" for respective OS.

-- load wasm_nvim
local wasm = require("wasm_nvim")

-- this next line scan and load .wasm files into space
-- should be called only once, preferebly on your init.lua
wasm.setup {
  --debug = true -- uncomment to see debug info printed out, good for debugging issues.
}

-- Here tests is a wasm file, test.wasm inside a ./wasm folder
-- located in neovim runtimepath.
-- The luaExecExample is an example of a function exposed by the test.wasm module.
wasm.tests.luaExecExample();

Building from source

cargo make build

Then move the shared library from /target/release/*.so or *.dll to a ./lua folder on the neovim runtime path so as to use it.

Requirements:

  • Cargo Make cargo install cargo-make

Required by Module

  • a function called functionality that is exposed/exported so that it can be called from wasm_nvim library. The function returns a json defining what functions are exported, and what they take as parameters, also what they return.

    An example:

    export fn functionality() u32 {
        var functions = ArrayList(Functionality).init(aloc);
        _ = functions.append(CreateFunctionality("hi", "void", "void")) catch undefined;
        var stringified = ArrayList(u8).init(aloc);
        json.stringify(functions.items, .{}, stringified.writer()) catch undefined;
        var unmanaged = stringified.moveToUnmanaged();
        // get id for setting a value
        const id = get_id();
        const addr = get_addr(&unmanaged.items[0]);
        //set the value to be consumed as a return type of this function
        set_value(id, addr, unmanaged.items.len);
        return id;
    }
    

    it returns an id, that maps to a json which was created by the set_value() function, which points to a json string that defines the functions and parameters exported by the module to be consumed. In this case the json would like like bellow:

    [{"name":"hi", "params": "void", "returns": "void"}]
    • Params field: Can be "void" or anything else, doesn't really matter. When "void" means the function tagged by "name" consumes/accepts nothing.

    • Returns field: Same situation as Params field above, anything but void means the function returns something, else returns void.

      These fields are necessary when functions are being exported by wasm module, so that lua end that might call them has ability to get values if they are returned, or pass value to the function if it is expecting some.

Neovim APIs implementation with custom interface for more wasm juice

This section exists, because we currently can't directly interact with Neovim API's that require lua function as references or callbacks in parameters, so users might need to wrap their wasm callbacks into a lua function, and make the neovim api from that side as a solution for the time being. NOTE: If you come across a neovim api that requires a lua function or callback in params, then make a PR to the ./API.MD file adding it to the list, or you can also create an issue.

Exposed Useful Functions from Wasm_Nvim That can be consumed by modules.

Examples Bellow use zig

  • extern "host" get_id() u32;

    Get a unique id to be used for sharing data between wasm module and outside world.

  • extern "host" get_addr(*u8) u32;

    Get the address from the host in terms of the memory of the module

  • extern "host" get_value_addr(id: u32) [*]u8;

    Usable for getting location of value that was created from outside world of module. The value pointed here is to be managed by the module, and deallocated. NOTE: value is cleared from memory of outside world once called, make sure to call before get_value_size, so as to know the length before calling this function

  • extern "host" get_value_size(id: u32) u32;

    Given an id to a value, it returns the size of the value located at given id. This should be called before get_value_addr as that would clear the id from memory.

    s

  • extern "host" set_value(id: u32, loc: u32, size: u32) void;

    Used for returning/setting a value to the wasm_nvim library or to the outside world from the wasm module using it. Users of this method should make sure the relinquish memory control of any thing the pointer is pointing to.

  • extern "host" lua_exec(id: u32) void;

    Executes lua script which is string, created, and passed to host via get_id andset_value combination, the id of the string is then passed to this function which it will then be executed.

    NOTE: This prints out the loaded string to output on some neovim versions, eg: 0.9.1 on windows.

  • extern "host"lua_eval(id: u32) u32;

    Similar to lua_exec except that this one evaluates expressions and will return a value that is mapped to the id. The value returned will say "null", if the expression evaluated returned nothing, otherwise the value would contain the contents of the results

    NOTE: This is for expressions, anything else passed to this function can result to undefined behavior

Tutorial

More Repositories

1

kplc-outage-parser

A library to give output of latest data from kplc outages pdf @ https://kplc.co.ke/category/view/50/planned-power-interruptions
Rust
11
star
2

kplc-outage-server

A server that uses the kplc-outage-parser to parse and produce json
Rust
11
star
3

rt3290-linux-drivers

Improves connectivity strength and therefore speed on your ralink rt3290 model version.
C
9
star
4

save-me-baby

A plugin that enables auto saving to remote git repo
TypeScript
9
star
5

wakarizer

Boost Wakatimes, :).
Go
7
star
6

nuru-lsp

Unofficial NURU LSP server
Go
5
star
7

4coder_cmake_builder

A cmake file to build custom layer of 4coder, also generates compile_commands.json for lsp servers.
CMake
4
star
8

nvimrc

My nvim [dot] files setup
Lua
4
star
9

near-bnb

An Air BNB system using NEAR blockchain
TypeScript
4
star
10

Pesapal

Answers to the Pesapal 2023 Junior dev challenge @ https://pesapal.freshteam.com/jobs/2OU7qEKgG4DR/junior-developer-23
TypeScript
3
star
11

AOC2021

Advent Of Code 2021, in Rust
Rust
2
star
12

web2txt----txt2web

Used to turn website links to text links that are easy to understand but not recodnized by link blocking websites
C++
2
star
13

Advent-of-code-2022

AOC 22
Rust
2
star
14

wakaflame

A wakatime data displayer for Kenyan devs
TypeScript
2
star
15

react-tut-official

Did the react tutorial from official website.
JavaScript
2
star
16

.emacs.d

Emacs Config
Emacs Lisp
2
star
17

wakaflame-server

proxy server in rust for wakaflame project
Rust
2
star
18

rust-book

Rust book main examples
Rust
2
star
19

PlayListPlayer

A playlist video player using VLC on backend
C++
2
star
20

vimrc

Clean vimrc
Vim Script
2
star
21

ke_counties

Library for getting information on size, area of counties in Kenya
Java
2
star
22

Journals

Java
1
star
23

Decitizen

Validate Kenyan ID using Name and year of birth
TypeScript
1
star
24

pyProgramming_Collective_intelligence

Python
1
star
25

ALC2.0-final

Final Project for Andela Learning Challenge 2.0
1
star
26

OSSRH-70383

1
star
27

bucky-react-creator

Create buck-react webpages.
C++
1
star
28

ColorBox

1
star
29

C-Proxy-For-Debian-Ubuntu

C++
1
star
30

Encode-Decode

1
star
31

C-GUI-ProxyChanger-Ubuntu-Debian

Makefile
1
star
32

BOrweStock

Completion of Andela Challenge November 6 involving calculating currencies
Java
1
star
33

at-mombasa

CSS
1
star
34

System-GC

A GC javaagent
Java
1
star
35

BOCyber

Java
1
star
36

angular-ng-book

Tuts from Angular ng-book
TypeScript
1
star
37

jenga-api

A rust implementation.
Rust
1
star
38

codechef_ans

Answers to codechef practice problems.
Rust
1
star
39

SDL-Arch-Brigthness

C++
1
star
40

mpesa-async-rs

An Mpesa async library for rust
Rust
1
star
41

PythonSpeedTests

Python Speed tests
Python
1
star
42

algorithms

Java
1
star
43

PlayListPlayerFX

A javaFX media playlist player, using vlc
Java
1
star
44

vim-vimrc-refresher

Allows you to quickly refresh your vimrc, reloaing plugins, etc.
Vim Script
1
star
45

portfolio

Code that goes to showing & running my portfolio
TypeScript
1
star
46

AAD-Google

Java
1
star
47

stickman_world

Stick Man multiplayer button chacers
TypeScript
1
star
48

JSouthParkDownloader

A simple java application that scraps and downloads Episodes from Southpark from http://sp.lolfile.com/episodes
Java
1
star
49

jenga-rs

Rust library to expose Jenga API https://developer.jengaapi.io/
Shell
1
star
50

python-crash_course

Python
1
star
51

zellig

ZelliJ Plugin API for Zig
Zig
1
star
52

AOC23

Advent of code, in dart
Dart
1
star
53

ProfileCard

Kotlin
1
star
54

kt_vs_dart_vs_rust_vs_wasm

Example app to check performance between Kotlin, Dart, Rust and Wasm
Dart
1
star
55

dfx-universal

Universal DFX implementation that works with docker on any OS
TypeScript
1
star