20161113-nodefest

00580f6c11851d2fff0b3e2f7392226b?s=47 N. Shimizu
November 13, 2016

 20161113-nodefest

00580f6c11851d2fff0b3e2f7392226b?s=128

N. Shimizu

November 13, 2016
Tweet

Transcript

  1. JavaScriptでの並列プログラミング: 共有メモリーと不可分操作、ロック N.Shimizu (nshimizu@mozilla-japan.org) 東京node学園祭(2016/11/13)

  2. N. Shimizu / @chikoski •Mozilla Japan で Developer relation (エヴァンジェリスト)をしています


    JavaScript, asm.js, WASM, DevTools, Rust, etc •ドキュメントの翻訳や、製品の翻訳も行なっています •コミュニティ活動: •html5j Web プラットフォーム部 / ゲーム部 •We are JavaScripters •プログラミング言語そのものが好きです •https://speakderdeck.com/chikoski/
  3. None
  4. None
  5. Proudly non-profit, Mozilla makes products like Firefox with a mission

    to keep the power of the Web in the hands of users everywhere. Mozilla Mission (https://www.mozilla.org/en-US/mission/)
  6. Our mission is to promote openness, innovation & opportunity on

    the Web. Mozilla Mission(https://www.mozilla.org/en-US/mission/)
  7. Project Positron(Geckoを使用したElectron互換のアプリシェル) : https://github.com/mozilla/positron

  8. JavaScriptはメインスレッドの時間を譲り合って共有します • 非同期処理を行うことで、実行時間を他のプログラムに譲れます • 例:アニメーション • スケジューラーがある場合:アニメーションを行う長い繰り返し処理 • JS: 1フレームごとの処理に分割し、window.requestAnimationFrameで他のプログラムに時間を譲る

    1フレームの処理 1フレームの処理 1フレームの処理 非同期
 処理 非同期
 処理 非同期
 処理 他の処理 他の処理
  9. GVODUJPOVQEBUF \ CFGPSF6QEBUF  VQEBUF0CKFDU4UBUVT  VQEBUF(SBQIJDT  BGUFS6QBUF 

    XJOEPXSFRVFTU"OJNBUJPO'SBNF VQEBUF  ^  window.requestAnimationFrame を利用したアニメーションの描画ループ
  10. WPJENBJO \ XIJMF USVF \ֿך搀ꣲٕ٦فכ04ח״׏גծ黝㹅♧儗⨡姺ׁ׸תׅ CFGPSF@VQEBUF  VQEBUF@PCKFDU@TUBUVT  VQEBUF@HSBQIJDT

     BGUFS@VQEBUF  ^ ^ 典型的なアニメーションループ
  11. GVODUJPOEP5BTL \ EP5BTL"  EP5BTL#  EP5BTL$  EP5BTL% 

    ^ אה׮װ׷חכ儗꟦ַַָ׶ֺׅ׷ GVODUJPOEP5BTL \ EP5BTL"  EP5BTL#  XJOEPXTFU*NNFEJBUF \ EP5BTL$  EP5BTL%  ^  ^ window.setImmediateを利用した、明示的な処理時間の移譲
  12. GVODUJPOMPX1SJPSJUZ5BTL EFBEMJOF \ JG EFBEMJOFUJNF3FNBJOJOH  \ EP4PNFUIJOH  ^

    ^ XJOEPXSFRVFTU*EMF$BMMCBDL MPX1SJPSJUZ5BTL  XJOEPXSFRVFTU*EMF$BMMCBDL MPX1SJPSJUZ5BTL \UJNFPVU^  空き時間にする処理の登録
  13. メインスレッドだけを効率よく使うには • 仕事を適切な粒度に分解して、分解された仕事と仕事の間に適切に非同期処理を入れてやる • window.requestAnimationFrame • window.setTimeout, window.setInterval, window.setImmediate •

    隙間時間に仕事をうまく入れていく: window.requestIdleCallBack • 1つのスレッドを効率よく使う、というアプローチには限界があります • 凝集度が下がり、プログラムは読みにくくなります • 仕事をどうしても分割できない場合もあります
  14. マルチスレッドプログラミング

  15. マルチスレッドプログラムとは • 複数の処理の流れ(スレッド)を利用するプログラムのこと • JavaScriptではWeb Workersを利用することで、マルチスレッドプログラムを実現できます taskA taskB TaskC taskD

    taskA taskB taskA taskD taskD taskD taskD taskD taskD
  16. DPOTUXPSLFSOFX8PSLFS XPSLFSKT 8PSLFSך⡲䧭 8PSLFSַ׵ךًحإ٦آ׾「ֽ《׷عٝسٓ XPSLFSPONFTTBHFNFTTBHF\ DPOTUEBUBNFTTBHFEBUB EPTPNFUIJOH ^ ً؎ٝفؚٗٓيַ׵8PSLFSפךًحإ٦آך鷏⥋
 XPSLFSTFOE.FTTBHF

    \DPNNBOETVN OVNCFST<   >^  Workerを利用するプログラムの例:mainスレッド側
  17. JNQPSU4DSJQUT DPNNBOEKT أؙٔفزך؎ٝه٦ز PONFTTBHFFWFOU\ DPOTUEBUBNFTTBHFEBUB DPOTU\OBNF OVNCFST^EBUB DPOTUDPNNBOEHFU$PNNBOE#Z/BNF OBNF 

    DPOTUSFTVMUDPNNBOE OVNCFST  QPTU.FTTBHF \DPNNBOEOBNF SFTVMUSFTVMU^  ^ Workerを利用するプログラムの例:ワーカースレッド側
  18. DPOTUPCK\WBMVF^ XPSLFSQPTU.FTTBHF PCK  XPSLFSPONFTTBHF EBUB\ DPOTPMFMPH PCKEBUB  ^

     PONFTTBHFGVODUJPO EBUB \ QPTU.FTTBHF EBUB  ^ main worker メッセージを通じて渡されるオブジェクトはコピーされる
  19. ArrayBuffer:固定長のバイト列 • 固定長のバイナリーデータを扱うためのデータ構造です • 各要素へ直接アクセスすることはできません IUUQDBOJVTFDPNTFBSDI"SSBZ#VGGFS

  20. DPOTUCVGGFSOFX"SSBZ#VGGFS  غ؎زך㔿㹀ꞿךꂁ⴨׾然⥂ DPOTUWJFXOFX*OU"SSBZ CVGGFS  غ؎زךꂁ⴨׾ؽحزך侭侧ךꂁ⴨ה׃ג،ؙإأׅ׷׋׭ךؽُ٦׾⡲䧭 GPS MFUJJWJFXMFOHUIJ \

    WJFX<J>.BUIGMPPS .BUISBOEPN  /VNCFS."9@4"'&@*/5&(&3  ^ 格納するデータの種類に合わせたビューを作成し、そのビューを通じてアクセスする
  21. ؽُ٦ ؟؎ؤ 铡僇 ず瘝ך$ך㘗 *OU"SSBZ  痗〾אֹ侭侧ך酡侧 JOU@U 6JOU"SSBZ 

    痗〾ז׃侭侧 VJOU@U 6JOU$MBNQU"SSBZ  痗〾ז׃侭侧ؙٓٝف VJOU@U *OU"SSBZ  痗〾אֹ侭侧ך酡侧 JOU@U 6JOU"SSBZ  痗〾ז׃侭侧 VJOU@U *OU"SSBZ  痗〾אֹ侭侧ך酡侧 JOU@U 6*OU"SSBZ  痗〾ז׃侭侧 VJOU@U 'MPBU"SSBZ  嵤⹛㼭侧挿 PBU 'MPBU"SSBZ  ⦓礵䏝嵤⹛㼭侧挿 EPVCMF
  22. GFUDI BFODPEFE  UIFO SSBSSBZ#VGGFS  UIFO CVG\ XPSLFSQPTU.FTTBHF CVG

     ^  XPSLFSPO.FTTBHFEP4PNF5IJOH PONFTTBHFGVODUJPO EBUB \ DPOTUWJFX OFX*OU"SSBZ EBUB  EFDPEF WJFX  QPTU.FTTBHF WJFXCVGGFS  ^ データがなんどもコピーされて非効率 main worker
  23. DPOTUCVGGFSOFX"SSBZ#VGGFS   GVODUJPOUSBOTGFS \ DPOTPMFMPH CVGGFS խ"SSBZ#VGGFS\CZUF-FOHUI^ XPSLFSQPTU.FTTBHF CVGGFS

    <CVGGFS>  DPOTPMFMPH CVGGFS "SSBZ#VGGFS\CZUF-FOHUI^ DPOTPMFMPH CVGGFSCVGGFS USVF ^ ArrayBufferは、その所有権をスレッド間で移動できます
  24. GFUDI BFODPEFE  UIFO SSBSSBZ#VGGFS  UIFO CVG\ XPSLFSQPTU.FTTBHF CVG

    <CVG>  ^  XPSLFSPO.FTTBHFEP4PNF5IJOH
 PONFTTBHFGVODUJPO EBUB \ DPOTUWJFX OFX*OU"SSBZ EBUB  EFDPEF WJFX  QPTU.FTTBHF WJFXCVGGFS  <WJFXCVGGFS>  ^ 所有権の移動を利用したコード main worker
  25. メインスレッドをブロックしなくても、重たい処理を行えるように • Web Workers を利用することで、メインスレッド以外にスレッドを作成できます • 作成したスレッドで重たい処理をすれば、メインスレッドを占有することはありません • 大きなArrayBufferは所有権を移動させることで、効率よく転送できます fetch

    task decode doSomething task task task task task QPTU.FTTBHF QPTU.FTTBHF
  26. 3つ以上のスレッドで、ArrayBufferを共有するには? • データを利用した処理を複数の主体で行う場合もあります • 同じデーターに対して、異なる処理をする場合 • 同じデーターの異なる部分に対して、同じ処理をする場合 • 所有権は1つのスレッドしか持てないので、データをコピーするしかない? أٖحس

    "SSBZ#VGGFS أٖحس "SSBZ#VGGFS ずׄ"SSBZ#VGGFS׾䭯ג׷ךַ
  27. SharedArrayBuffer • スレッド間で共有可能なArrayBuffer • ArrayBuffer同様、ビュー経由で要素にアクセスします • "ECMAScript Shared Memory and

    Atomics" で提案中です
 http://tc39.github.io/ecmascript_sharedmem/shmem.html أٖحس 4IBSFE"SSBZ#VGGFS أٖحس 4IBSFE"SSBZ#VGGFS 4IBSFE"SSBZ#VGGFS
  28. DPOTUCVGGFSOFX4IBSFE"SSBZ#VGGFS   GVODUJPOUSBOTGFS \ DPOTPMFMPH CVGGFS խ4IBSFE"SSBZ#VGGFS\CZUF-FOHUI^ XPSLFSQPTU.FTTBHF CVGGFS

    <CVGGFS>  DPOTPMFMPH CVGGFS 4IBSFE"SSBZ#VGGFS\CZUF-FOHUI^ DPOTPMFMPH CVGGFSCVGGFS USVF ^ 共有されているので、postMessageで受け渡した後も領域を参照できます
  29. DPOTUIFBQ OFX6*OU"SSBZ CVGGFS  IFBQ<>IFBQ<>  DPOTUIFBQ OFX6*OU"SSBZ CVGGFS 

    IFBQ<> 2つの計算が終わった時、view[0] にはなにが入っているでしょうか? threadA threadB
  30. heap[0] = heap[0] == 0 ? 2 : 0; はいくつかの処理に分割されます

    a = [0]; a = a + 2; view[0] = a; view[0] = 1; a = view[0]; a = a + 2; view[0] = a; view[0] = 1; a = view[0]; a = a + 2; view[0] = a; view[0] = 1;
  31. 共有メモリには、Atomicsオブジェクトの提供する不可分操作を利用してアクセス します DPOTUIFBQOFX6*OU"SSBZ CVGGFS  "UPNJDTDPNQBSF&YIBOHF IFBQ   

     DPOTUIFBQOFX6*OU"SSBZ CVGGFS  IFBQ<>IFBQ<>  Atomics利用 Atomicsなし
  32. ꟼ侧 铡僇 "UPNJDTBEE 䭷㹀⡘縧ך⦼הך⸇皾׾遤ְծ׉ך穠卓׾׉ך⡘縧ח剅ֹ䨱ׅ "UPNJDTBOE 䭷㹀⡘縧ך⦼הך锷椚琎׾鎘皾ׅ׷ "UPNJDTDPNQBSF&YDIBOHF 䭷㹀⡘縧ך⦼ה嫰鯰׾遤ְծ瘝׃ְ㜥さծ׉ך⡘縧ך⦼׾縧ֹ䳔ִ׷ "UPNJDTFYDIBOHF 䭷㹀⡘縧ך⦼׾ծⴽך⦼הⰅ׸剏ִ׷

    "UPNJDTMPBE 䭷㹀⦼ך⦼׾《䖤ׅ׷ "UPNJDTPS 䭷㹀⡘縧ך⦼הך锷椚ㄤ׾鎘皾ׅ׷ "UPNJDTTUPSF 䭷㹀⡘縧ח⦼׾鏣㹀ׅ׷ "UPNJDTTVC 䭷㹀⡘縧ך⦼הך幾皾׾遤ְծ׉ך穠卓׾׉ך⡘縧ח剅ֹ䨱ׅ "UPNJDTYPS 䭷㹀⡘縧ך⦼הך䱖➭涸锷椚ㄤ׾鎘皾ׅ׷
  33. 食事する哲学者の問題 • 複数プロセスの同期制御に関する古典的な問題 • 問題: • 哲学者が円卓を囲んでいる • 哲学者はときおり考えるのやめて、食事をする •

    食事には2本のフォークが必要で、
 一度には1本のフォークしかとれない • 哲学者同士は会話をしない • 哲学者は食事することがきるだろうか? IUUQTKBXJLJQFEJBPSHXJLJ굸✲ׅ׷ㆸ㷕罏ך㉏겗
  34. Atomics.wait / Atomics.wake • 特定の条件が true になるまで待つ手段 • 待っている間、処理はその式でブロックされる •

    起動されると、その式以降から実行が継続されます • 条件の指定方法、 • 共有された指定位置の値が、指定された値と等しい間、待ちます • 使用できるのは、共有されたInt32Arrayのみ • Atomics.waitをメインスレッドで呼ぶことはできません
  35. XPSLFSQPTU.FTTBHF IFBQCVGGFFS  <IFBQCVGGFS>  EP4PNFUIJOH "UPNJDTXBLF IFBQ  

    "UPNJDTTUPSF IFBQ    "UPNJDTXBLF IFBQ   PONFTTBHFGVODUJPO CVGGFS \ DPOTUIFBQ OFX6*OU"SSBZ CVGGFS  DPOTPMFMPH "UPNJDTMPBE IFBQ   "UPNJDTXBJU IFBQ    DPOTPMFMPH "UPNJDTMPBE IFBQ   main worker 起こすメインスレッドと、待つワーカースレッド
  36. DPOTU7"-*% DPOTU*/7"-*% "UPNJDTTUPSF IFBQ  */7"-*%  XPSLFSQPTU.FTTBHF IFBQCVGGFS 

    <IFBQCVGGFS>  QSPEVDF IFBQ  "UPNJDTTUPSF IFBQ  7"-%*%  "UPNJDTXBLF IFBQ   DPOTU*/7"-*% PONFTTBHFGVODUJPO CVGGFS \ DPOTUIFBQ OFX6*OU"SSBZ CVGGFS  "UPNJDTXBJU IFBQ  */7"-*%  DPOTVNF IFBQ  ^ main worker 生産者と消費者
  37. DPOTU4*(/"&-&% DPOTU&7&/5@" GVODUJPOGJSF RVFVF FWFOU5ZQF \ "UPNJDTTUPSF RVFVF  FWFOU5ZQF

     4*(/"-&%  "UPNJDTXBLF RVFVF FWFOU5ZQF  ^ GJSF RVFVF &7&/5@"  DPOTU6/4*(/"-&% DPOTU&7&/5@" "UPNJDTXBJU RVFVF  &7&/5@"  6/4*(/"-&%  IBOEM&WFOU"  main worker Event object
  38. IUUQTCMPHTVOJUZEDPNKQVQEBUFEXFCHMCFODINBSLSFTVMUT

  39. .BJO5ISFBE 8PSLFS5ISFBE CVGGFS CVGGFS CVGGFS CVGGFS CVGGFS CVGGFS CVGGFS DPQZ

    5SBOTGFS 3FGFS 3FGFS DPOTUCVGGFSOFX"SSBZ#VGGFS   XPSLFSQPTU.FTTBHF CVGGFS  DPOTUCVGGFSOFX"SSBZ#VGGFS   XPSLFSQPTU.FTTBHF CVGGFS <CVGGFS>  DPOTUCVGGFSOFX4IBSFE"SSBZ#VGGFS   XPSLFSQPTU.FTTBHF CVGGFS <CVGGFS>