Comparaison des performances entre JavaScript natif multi-threads et WASM

Auteur:Inventeur de la quantification, Date: 23 février 2023 à 17h35h24
Les étiquettes:Les fils multiples

L'inventeur a essayé de quantifier les efforts de Javascript pour prendre en charge les multiples threads véritablement significatifs à partir de la couche inférieure native, et a ajouté la fonctionnalité WASM, ci-dessous une démo pour les nouveaux hôtes à télécharger. Cette fonctionnalité est une fonctionnalité non JavaScript Worker qui permet de communiquer entre plusieurs fils ou avec le fils principal.

Les tests sont générés à partir de ce site:https://wasdk.github.io/WasmFiddle/

Voici le code de la langue C compilé sous wasm:

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

Compiler et télécharger le fichier wasm puis le convertir en une chaîne hex en python

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

Le contenu derrière les variables dans le code de remplacement peut être

__Thread ((fonction, arguments...)

Créer un thread et retourner le threadtid, les fonctions de la fonction principale du thread accepté doivent compléter tout le code de la fonction dans la fonction du thread, ne prend pas en charge les références à d'autres fonctions de clôture, peut appeler toutes les API de la plate-forme dans le thread, mais ne peut pas appeler d'autres fonctions personnalisées par l'utilisateur

Voici un exemple simple:

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

Exemples de requêtes à plusieurs fils:

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

Variables de stockage local du thread

Prise en charge des variables de stockage local des threads pour faciliter le partage de données, les données ne sont pas stockées dans les threads__threadJoinAttendre de réussir à se retirer ou__threadTerminateEn cas de résiliation

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

tid est 0 pour indiquer le fil courant, value non spécifié pour indiquer la clé de suppression, supporte l'accès mutuel partagé des variables entre les fils, les valeurs doivent être sérialisables

Communication par fil

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

Je ne peux pas le faire.

S'il n'est pas possible de spécifier un délai d'attente, il faut attendre la fin du thread, retourner avec succès une structure contenant une valeur de retour de la fonction et récupérer les ressources, la structure est la suivante:

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

Si l'intervalle retourne undefined

__threadTerminate (en anglais seulement)

Forcer la fin du thread et récupérer les ressources (on ne peut plus utiliser __threadJoin en attendant la fin)

Attention!

La fonction __Thread ne prend pas en charge les variables en dehors de la fonction de référence (pour un fonctionnement en milieu isolé), la référence à des variables externes sera un échec de compilation.


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

Relationnée

Plus de

Le couteau à osAstuce d'exécution: erreur ReferenceError: '__Thread' n'est pas défini à main (FILE:5)

Inventeur de la quantificationMise à niveau vers le dernier hôte