Morris's blog

瀏覽器上的threading - web workers

2020-05-10

集合吧!threading廚們!!

  • threading與我: 在一開始學應用程式開發的時候接觸Android programing, 後來也自己摸過一點點swift,也寫過JAVA swing(年代久遠的一個東西...用JAVA做desktop的應用程式),在寫JAVA server的時期也會用各種多執行緒的API(如ExecutorService,跟執行環境要一個thread-pool)同時用多個執行緒來加速流程的進行(同時聯絡其他多台server, 同時寄信...etc)
  • 那在web-UI上的開發呢? web應用程式開發上以前一直有一個痛點,就是沒辦法自己開執行緒,很多時候開發者們也覺得好像沒那個必要,因為js在做各種network-io(就是指打rest API)的時候,執行環境所提供的API(XMLHttpRequest, fetch)天生就是非堵塞的(non-blocking),在做network-io的時候背後是瀏覽器在進行,JS的mainThread並不會被堵塞住,這些工作都是io-bound的,那如果今天要做的事情是cpu-bound的話呢?

cpu-bound task

對資料跑迴圈做某種處理,access某個變數再取底下的某個屬性的值......這樣子的事情其實都是cpu在做事,但是因為今天的裝置的cpu運算速度都非常快,在一般處理生活大小事的應用程式上(所以我指的不是畫圖畫很大的那種電子遊戲),只要不是變成無限迴圈的狀況的話,通常UI也不會卡住停下來的感覺,但是要是我們今天要做某些非常激烈的數學運算,像是從100萬筆資料中找到最小的100個數,然後再把它們相加....之類的事,要是直接在JS上的mainThread上做,就會造成程式執行到那個地方的時候卡在那邊做那個運算(其實是因為遍歷那100萬筆資料太花時間),就沒辦法回應UI上的反應(如文字輸入,輸入游標甚至不會閃爍,會整個停止), 這就是一個在極端狀況下可能會遇到的問題。

Web Wrokers api

  • mdn - web workers
  • 它是HTML5裡的標準之一,所以其實是已經被實作好一段時間的API了。
  • 從上面的文件中可以看到,這是個可以讓開發者自己決定什麼時候要開啟一個新的執行緒來做事的API,當然它是不能夠直接去操作畫面的,這在各種UI-programing上都是這樣,能夠直接操作畫面的只有mainThread。
  • 要在workerThread上做的事情要寫在一個獨立的script裡,然後在創出workerThread時去載入那個script。
  • 它必須要使用一種叫postMessage的API來做mainThread與workerThread之間的聯絡。這也造成它使用上非常地繁瑣。
  • 作者: Surma
  • Surma是Google developer Advocate - web team裡的其中一人,Jake Archibald的同事。兩人常常一起在Google Chrome Developers這個youtube頻道上的 http 203單元上出現
  • 在2019/05的Google I/O上, Google developer Advocator web team就一起發表了一個project - PROXX,它是一個在瀏覽器上玩的踩地雷遊戲,為了讓遊戲體驗更順暢,它們選擇讓各種計算都在 worker threads上去做,以讓main thread能夠完全專心在更新畫面與跟user互動

為什麼應該使用Comlink來操作web worker?

  • 簡化流程,可以不用使用不是很好用的 postMessage API來做執行緒之間的交互。
  • 可以把 讓某件事在web-worker上做這樣的事情直接模組化(想到就讓人衝動)。
  • 讓載入某件事的code這樣的事可以用import的(須搭配webpack的特定plugin)

使用感想

  • 我在工作上的某次需要做到有點份量的數學運算的程式裡測試用來玩玩看,該專案react based。
  • 用了之後再用lighthouse去測performance,其實first cpu idle time並沒有比較提昇,因為其實我的程式裡的運算量還不算大,就算不使用web workers,只要計算過程的code不要寫得太差的話,在mainThread上其實算不到0.5秒
  • 但是我有測試要是我故意讓計算過程會算很久,好比20秒以上(例如跑一個while迴圈裡面不斷 +=1,直到超過60000000...才跳出迴圈),效果就真的是非常驚人,就算故意做了這樣的事,UI也不會有任何的lag感(照樣可以很順地捲動頁面,如果不使用web workers的話,會讓chrome跳出要不要終止網頁的提示視窗....)。

這邊有一篇實戰超級好文,可以直接看這篇來try

REFERENCE

response