Perbandingan kinerja JavaScript multi-threaded asli dengan WASM

Penulis:Penemu Kuantitas, Tanggal: 2023-02-23 17:35:24
Tag:Berbagai thread

Penemu mencoba untuk mengkuantifikasi Javascript untuk mendukung multi-thread yang benar-benar bermakna dari tingkat bawah asli, dan menambahkan fitur WASM. Di bawah ini adalah DEMO untuk mengunduh host terbaru untuk merasakan pengalaman baru. Fungsi ini adalah fungsi Worker non-Javascript, yang dapat digunakan untuk berkomunikasi antara beberapa thread atau berkomunikasi dengan thread utama.

Perangkat lunak ini dapat digunakan untuk membuat tes dari situs web berikut:https://wasdk.github.io/WasmFiddle/

Kode bahasa C yang dikompilasi sebagai wasm adalah sebagai berikut:

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

Mengkompilasi dan mengunduh file wasm dan mengubahnya menjadi string hex dengan python

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

Anda dapat mengubah kata sandi yang ada di belakang variabel.

__Thread ((fungsi, argumen...)

Menciptakan thread dan mengembalikan threadtid, fungsi dari fungsi subjek thread yang diterima harus menyelesaikan semua kode fungsi di dalam fungsi thread, tidak mendukung referensi untuk fungsi penutupan lainnya, dapat memanggil semua API platform di dalam thread, tetapi tidak dapat memanggil fungsi lain yang disesuaikan pengguna

Contoh sederhana:

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

Contoh permintaan multi-thread:

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 yang disimpan secara lokal pada thread

Mendukung variabel penyimpanan lokal pada thread, untuk memudahkan berbagi data, data yang tidak tersimpan pada thread__threadJoinMenunggu untuk berhasil keluar atau__threadTerminateEfektif dalam kasus penghentian

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

tid adalah 0 untuk menunjukkan thread saat ini, value tidak ditentukan untuk menunjukkan delete key, mendukung variabel berbagi akses antar thread, nilai harus menjadi variabel yang dapat diurutkan

Komunikasi dengan kabel

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

{\fnCandara\fs60\b1\4cH000000\4aH80}Join, timeout. {\fnCandara\fs60\b1\4cH000000\4cH000000\4aH80}Aku tidak tahu.

Menunggu akhir thread menentukan timeout (millisecond) untuk menentukan waktu tunggu yang tidak dapat ditentukan yaitu menunggu sampai akhir thread, berhasil mengembalikan struktur yang berisi nilai fungsi dan mengembalikan sumber daya, struktur sebagai berikut:

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

Jika waktu mundur kembali undefined

__threadTerminate ((tid)

Memaksa terminasi thread, dan merebut kembali sumber daya (tidak dapat lagi menggunakan __threadJoin untuk menunggu terminasi)

Hati-hati

Fungsi __Thread tidak mendukung variabel referensi di luar fungsi (untuk menjalankan lingkungan isolasi), referensi variabel eksternal akan gagal dikompilasi


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 banyak

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

Penemu KuantitasUpgrade ke host terbaru