Comparison of native multi-threaded JavaScript and WASM performance

Author: Inventors quantified, Date: 2023-02-23 17:35:24
Tags: Multi-threaded

The inventors quantified the attempt to make JavaScript support true meaningful multi-threaded from the native low-level, and added WASM functionality, below is a DEMO to download the latest hosts for a taste of the experience This is a non-Javascript worker function that can be used to communicate between or with multiple threads within a single thread.

The C language translation wasm can be used to generate tests from this website:https://wasdk.github.io/WasmFiddle/

The C language code compiled as wasm is:

int fib(int f) {
  if (f < 2) return f;
  return fib(f - 1) + fib(f - 2);
}

Compile and download wasm files and convert them to hex strings in python

python -c "print('data:hex,'+bytes.hex(open('program.wasm','rb').read()))"

Substitute the content behind the variable in the code.

__Thread(function, arguments…)

Creates threads and returns thread tid, functions of the accepted thread subject function must complete all function code within the thread function, does not support references to other closure functions, can call all platform APIs within the thread, but cannot call other user-customized functions

A simple example:

let tid = __Thread(function(x, y) {
    return x + y
}, 1, 2)
Log(__threadJoin(tid))

Examples of multi-threaded requests:

function main() {
    let threads = [
        "https://www.baidu.com",
        "https://www.163.com"
    ].map(function(url) {
        return __Thread(function(url) {
            Log("GET", url)
            return HttpQuery(url)
        }, url)
    })
    threads.forEach(function(tid) {
        Log(__threadJoin(tid))
    })
}

Local storage of threads

Support for local storage of threads to facilitate data sharing, even if the data is not stored in threads__threadJoinWait for the exit to succeed or__threadTerminateEffective in the event of termination

__threadGetData(tid, key)
__threadSetData(tid, key, value)

tid is 0 indicating the current thread, value is unspecified indicating the deletion key, supports mutually accessible shared variables between threads, the value must be a serializable variable

Wired communication

__threadPostMessage(tid, msg) // 向指定线程发送消息, tid为0是向主线程即当前主函数发送, 在线程内部调用指向主线程回复消息, 该消息可以被EventLoop捕获
__threadPeekMessage(tid, timeout) // 从指定线程接收消息, 如果不指定timeout(毫秒)就一直等待, tid为0指等待主线程的消息

__threadJoin(tid, timeout)

Wait for the end of the thread Specify timeout (milli-seconds) For a specified wait timeout, you can not specify that you have to wait until the end of the thread, successfully return a structure that contains a function return value and recover the resource, the structure is as follows:

{
    id: tid, // 线程id
    elapsed: 1111, // 线程的运行时间(纳秒)
    terminated: false, // 线程是否被强制结束 
    ret: 123, // 线程函数的返回值
}

If the timeout returns undefined

__threadTerminate(tid)

Forced termination of threads, and resource recovery ((can no longer use __threadJoin pending termination)

Be careful.

The __Thread function does not support non-threaded variables (used as an isolated environment), and referring to external variables will result in compilation failure.


function main() {
    let cycle = 100
    let input = 30
    let threads = [
        __Thread(function(cycle, input) {
            function fib(f) {
                if (f < 2) return f
                return fib(f - 1) + fib(f - 2)
            }
            let ret = 0
            for (let i = 0; i < cycle; i++) {
                ret = fib(input);
                Log("javascript progress: ", i)
            }
            return 'javascript fib: ' + ret
        }, cycle, input),
        
        __Thread(function(cycle, input) {
            let data = 'data:hex,0061736d010000000186808080000160017f017f0382808080000100048480808000017000000583808080000100010681808080000007908080800002066d656d6f727902000366696200000aa480808000019e80808000000240200041024e0d0020000f0b2000417f6a10002000417e6a10006a0b'
            let m = wasm.parseModule(data)

            let instance = wasm.buildInstance(m, {
                stack_size: 65 * 1024 * 1024,
            })

            let ret = 0
            for (let i = 0; i < cycle; i++) {
                ret = instance.callFunction('fib', input)
                Log("wasm progress: ", i)
            }

            return 'wasm fib: ' + ret
        }, cycle, input)
    ]

    threads.forEach(function(tid) {
        let info = __threadJoin(tid)
        Log('#'+tid, info.ret, 'elapsed:', info.elapsed / 1e6, "#ff0000")
    })
}

Related

More

The bone knifeRunning tip: Error ReferenceError: '__Thread' is not defined at main (FILE:5)

Inventors quantifiedUpgrade to the latest host