three.js 中使用多線程以及性能測試

今天郭先生說一下WebWorker以及WebWorker在three.js中的應用。咱們都知道Javascript是單線程的,好比執行js代碼的同時UI渲染就會中止,對於多核CPU的點腦,這一點讓人難以接受,好在Web Worker的出現多少解決了一些問題。官方說Web Worker指的是一種可由腳本建立的後臺任務,任務執行中能夠向其建立者收發信息。要建立一個 Worker ,只須調用 Worker(URL) 構造函數,函數參數 URL 爲指定的腳本。關於Web Worker的更多知識請閱讀Web Worker。線案例請點擊博客原文數組

1. 在three.js中使用多線程

在three.js中使用Web Worker常常發生在大量計算形成CUP阻塞的狀況下,咱們舉一個例子,好比說咱們製做了1000個Mesh。多線程

讓他們簡單的動起來,CPU幾乎沒有什麼壓力,FPS會在60左右,可是若是讓這1000個Mesh的位置都須要大量計算才能獲得,那麼FPS就會很低(和計算量成負相關),下面是一段代碼函數

for(let i=0; i<num; i++) {
    let angle = positions[i].y / (1000 / (Math.PI * 10));
    positions[i].x = positions[i].x + Math.sin(angle);
    positions[i].z = positions[i].z + Math.cos(angle);
    positions[i].y = positions[i].y + 1;
        //上面就是簡單的位置變化,下面的代碼模擬複雜的變化,累加100000次(這是很是佔用線程的狀況)
    for(let j=1, total=1; j<=100000; j++) {
        total += j;
    }
    if(positions[i].y > 500) {
        positions[i].y = positions[i].y - 1000;
    }
}
for(var i=0; i<num; i++) {
    group.children[i].position.set(positions[i].x, positions[i].y, positions[i].z);
}

positions是儲存1000個Mesh位置信息的數組,group裏面儲存了全部的Mesh,每次渲染都更改positions的位置信息,而後給Group的每個Mesh設置新值,這種狀況下FPS會低至7FPS,轉動場景能夠很明顯的感受到卡頓。接下來咱們使用Web Worker處理這個問題,主線程代碼以下post

myWorker = new Worker('/static/js/worker.js');
myWorker.postMessage(positions);
myWorker.onmessage = e => {
    let positions = e.data;
    for(var i=0; i<num; i++) {
        group.children[i].position.set(positions[i].x, positions[i].y, positions[i].z);
    }
}

腳本代碼以下性能

onmessage = function(e) {
    let num = 1000;
    let positions = e.data;
    setInterval(e => {
        for(let i=0; i<num; i++) {
            let angle = positions[i].y / (1000 / (Math.PI * 10));
            positions[i].x = positions[i].x + Math.sin(angle);
            positions[i].z = positions[i].z + Math.cos(angle);
            positions[i].y = positions[i].y + 1;
            for(let j=1, total=1; j<=100000; j++) {
                total += j;
            }
            if(positions[i].y > 500) {
                positions[i].y = positions[i].y - 1000;
            }
        }
        postMessage(positions);
    }, 1000 / 60)
};

主要代碼和未使用Web Worker幾乎同樣,只不過是將處理位置的代碼放在新的線程中完成,setInterval定時器每一次完成位置計算都會經過postMessage(positions)將位置信息返回給主線程,主線程經過onmessage接受信息,返回對象的data屬性就是新的positions。這樣一來FPS能夠達到60左右,轉動場景感受的到卡頓。這是十分讓人欣喜的。測試

2. 性能分析

前面已經說了在每一次位置計算中作10萬次累加,未使用Web Worker的狀況下FPS降到了7,下面是更多的數據(數據僅作對比,和當前使用狀況以及配合有關)。spa

累加次數(萬次) 使用Web Worker 未使用Web Worker
1 60 60
3 60 39
5 60 26
7 60 11
9 60 8
11 60 6

這裏面能夠看出,無論是多麼大量的計算,使用Web Worker都不會影響主線程,可是對於未使用Web Worker影響是十分嚴重的,下面展現一下兩種狀況下電腦性能的對比線程

下面是未使用Web Workercode

下面是使用Web Worker對象

這裏能夠看出使用更多的線程能夠很明顯的提高CPU使用率。小夥伴們不妨打開線上案例親自測試一下。

 

轉載請註明地址:郭先生的博客

相關文章
相關標籤/搜索