Perbandingan prestasi JavaScript multithread asli dengan WASM

Penulis:Pencipta Kuantiti, Tarikh: 2023-02-23 17:35:24
Tag:Pelbagai benang

Pencipta cuba untuk mengukur Javascript untuk menyokong multi-thread yang benar-benar bermakna dari lapisan bawah asli dan menambah fungsi WASM, di bawah ini adalah demo untuk memuat turun hos terkini untuk menikmati pengalaman yang segar Fungsi ini adalah fungsi Worker bukan Javascript yang boleh digunakan untuk berkomunikasi antara satu sama lain dalam pelbagai utas atau berkomunikasi dengan utas utama.

Pertukaran bahasa C wasm boleh dibuat dari laman web ini:https://wasdk.github.io/WasmFiddle/

Kod bahasa C yang disusun sebagai wasm adalah sebagai berikut:

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

Mengemas kini file wasm dan menukarnya kepada hex dengan python

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

Mengubah isi di belakang pembolehubah dalam kod

__Thread ((fungsi, hujah...)

Mencipta thread dan mengembalikan threadtid, fungsi subjek thread yang diterima mesti menyelesaikan semua kod fungsi dalam fungsi thread, tidak menyokong rujukan kepada fungsi penutupan lain, semua API platform boleh dipanggil di dalam thread, tetapi tidak boleh memanggil fungsi lain yang disesuaikan pengguna

Contoh mudah:

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

Contoh permintaan berbilang benang:

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))
    })
}

Variabel simpanan dalam talian

Menyokong pemasangan pemboleh ubah tempatan dalam talian untuk memudahkan perkongsian data yang tidak disambungkan ke dalam talian.__threadJoinMenunggu untuk berjaya keluar atau__threadTerminateBerkesan jika tamat

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

tid adalah 0 untuk menunjukkan utas semasa, value tidak ditentukan untuk menunjukkan kunci penghapusan, menyokong pembahagian pembahagian pemboleh akses antara utas, nilai mestilah pemboleh urutan

Komunikasi dengan benang

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

_threadJoin ((tid, timeout)

Tunggu hujung benang menentukan timeout (mls) untuk menentukan masa tunggu yang tidak boleh ditentukan ialah menunggu sehingga akhir benang, berjaya mengembalikan struktur yang mengandungi nilai fungsi dan mendapatkan semula sumber, struktur seperti berikut

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

Jika masa lapang kembali undefined

__threadTerminate(tid)

Memaksa penamatan benang, dan mengambil semula sumber ((tidak boleh lagi menggunakan __threadJoin menunggu berakhir)

Perhatikan

Fungsi __Thread tidak menyokong rujukan kepada pembolehubah luar fungsi (untuk menjalankan persekitaran yang terasing), rujukan kepada pembolehubah luar akan gagal disusun


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")
    })
}

Berkaitan

Lebih lanjut

Pisau tulangPetua: ralat ReferenceError: '__Thread' is not defined at main (FILE:5)

Pencipta KuantitiMengemas kini ke hos terkini