Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践

2,188 views

Published on

HTML5 CONFERENCEでの発表資料です
https://events.html5j.org/conference/2018/11/session/

Published in: Technology
  • Be the first to comment

  • Be the first to like this

コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践

  1. 1. コンパイルターゲット⾔語としての
 WEBASSEMBLY、
 そしてLINEでの実践 Jun, LINE Corp. kawasako, LINE Corp.
  2. 2. ⾃⼰紹介 @uta_tti https://github.com/utatti
  3. 3. •プログラミング⾔語を作る、とは •Wasmをターゲット⾔語*にする
 WEB⾔語の設計 •Wasmバイトコードを⽣成する
 コンパイラの作成 •LINEでの実践 Agenda *コンパイルターゲット⾔語: コンパイラがコードジェネレーションで吐き出す⾔語 e.g. TypeScriptのターゲット⾔語はJavaScript
  4. 4. プログラミング⾔語を作る
  5. 5. ● Wasmのコンパイルターゲット⾔語としての可能性を調査
 ● Wasmに直接コンパイルする (v.s. LLVM IR) ● 容量をへらす ● ユースケースを考慮した設計 なぜ作る必要があるのか
  6. 6. ● https://github.com/utatti/kou ● A minimal language compiled into wasm bytecode The kou Programming Language
  7. 7. ● ⾔語を設計する ● ⾔語のコンパイラを書く プログラミング⾔語を作る
  8. 8. ● 機能と⽂法を決める
 ● 想定しているユースケース ● 好み プログラミング⾔語の設計
  9. 9. ● どういう⾔語を作りたいのか ● 他の⾔語のいいところを考えてみる 好みは重要
  10. 10. let fac = fn (n int) int { let res = if n == 1 { 1 } else { n * fac(n - 1) }; res } Example
  11. 11. let fac = fn (n int) int { let res = if n == 1 { 1 } else { n * fac(n - 1) }; res } 好み1: 型安全性
  12. 12. let fac = fn (n int) int { let res = if n == 1 { 1 } else { n * fac(n - 1) }; res } 好み2: Braces over indents Easier to parse
  13. 13. let fac = fn (n int) int { let res = if n == 1 { 1 } else { n * fac(n - 1) }; res } 好み3: Expression-oriented From Rust
  14. 14. ● Wasm: 現在仕様で作りやすいように
 ● WEB上動く: バイトコードの容量を⼩さく
 ● 想定ユーザー: JS開発者 ユースケース
  15. 15. let arr = [1, 2, 3, 4, 5]; let i = 0; while i < len(arr) { ... i = i + 1; } ユースケース1: Wasm Smaller bytecode output
  16. 16. let arr = [1, 2, 3, 4, 5]; let i = 0; while i < len(arr) { ... i = i + 1; } ユースケース2: ⽂法 C-like
  17. 17. ● ⾔語仕様書を書く ● EBNF (Extended Backus-Naur Form) ● | alternation ● () grouping ● [] option (0 or 1 times) ● {} repetition (0 to n times) ● 他の⾔語の仕様書を参考にすると良い ● The Go Programming Language ● https://golang.org/ref/spec 設計を形にする
  18. 18. いったんDEMO kouのリポジトリでも⾒れます!
 https://github.com/utatti/kou
  19. 19. ● The real work starts here...
 ● 😇 コンパイラを書く
  20. 20. Optim.
Code gen. コンパイラの構造 ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  21. 21. Optim.
Code gen.ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  22. 22. ● Lexical analyzer ● Source code → Token* stream ● *Token: プログラミング⾔語のalphabet ● e.g. "hello", 1234, if, else, {, } Lexer
  23. 23. Optim.
Code gen.ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  24. 24. ● Syntactic analyzer ● Token stream → *AST ● *AST: Abstract syntax tree ● コードをツリー化したもの Parser
  25. 25. Example: AST main Declaration ... Module Identifier Params FunctionExpr let main = fn () void { .. }
  26. 26. ● Parser generator ● EBNF → Parser
 ● Parser combinator ● e.g. Parsec in Haskell ● DSL for parser ● kou uses this
 ● Or just write from scratch How to write parser
  27. 27. Optim.
Code gen.ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  28. 28. ● Syntactic sugarの解除
 ● 難しくいうと: Isomorphismの適⽤ ● 簡単にいうと: あれとこれって同じっしょ、の適⽤ Desugarer
  29. 29. ● Unary +の解除 ● +1234 == 1234 ● 1-tupleの解除 ● (1234) == 1234 Example: Desugarer
  30. 30. Optim.
Code gen.ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  31. 31. ● Semantic analyzer ● Hindley-Milner type system Type checker
  32. 32. ● App for function application 
 let x: A function f(x: A): B f(x): B Example: Hindley-Milner type system
  33. 33. Optim.
Code gen.ParserLexer Source code Target code コンパイラ
 フロントエンド コンパイラ
 バックエンド Desugarer Type
  34. 34. ● AST → Target code (Wasm bytecode) ● 実際Wasmバイトコードを⽣成する部分 Code generator
  35. 35. Wasm
 bytecodeWATASTkou kou compiler Source code Target code
  36. 36. ● Specification ● https://webassembly.github.io/spec/core/
 ● Stack machine WebAssembly bytecode
  37. 37. ● Use stack to pass/return values ● v.s. Register machine
 ● e.g. WebAssembly VM, JVM Stack machine
  38. 38. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack
  39. 39. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 1
  40. 40. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 1 2
  41. 41. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 1 2 3
  42. 42. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 1
  43. 43. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 1 6 ← 2 * 3
  44. 44. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack
  45. 45. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 7 ← 1 + 6
  46. 46. Example: Stack machine 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 7
  47. 47. Example: Value types 1 + 2 * 3 ! i32.const 1 i32.const 2 i32.const 3 i32.mul i32.add Stack 7
  48. 48. ● Integer ● i32, i64 ● Floating-point number ● f32, f64 ● kou uses i32 and f64 ● i64 cannot be used directly in JS WebAssembly value types
  49. 49. ● Tuple ● (1, true, 1.5)
 ● Array ● [1, 2, 3, 4, 5]
 ● WebAssembly Memory Complex types
  50. 50. ● Linear
 ● Virtual
 ● JS⼜はWasmでメモリを宣⾔ ● (memory 1) WebAssembly Memory
  51. 51. ● Wasm has no high-level support for memory allocation ● ⼿動で管理するしか無い Memory allocation
  52. 52. Memory allocation 4 … 4 because the pointer itself uses i32 ● Wasm has no high-level support for memory allocation ● ⼿動で管理するしか無い
  53. 53. Memory allocation 4 … 16バイトください‼ ● Wasm has no high-level support for memory allocation ● ⼿動で管理するしか無い
  54. 54. Memory allocation 20 16 bytes … ● Wasm has no high-level support for memory allocation ● ⼿動で管理するしか無い
  55. 55. ● Array Complex type (again!) [1.0, 2.0, 3.0, 4.0, 5.0] ! "###$#######$#######$#######$#######$#######% & 5 & 1.0 & 2.0 & 3.0 & 4.0 & 5.0 & '###(#######(#######(#######(#######(#######) 4 + 8 * 5 = 44 bytes
  56. 56. ● Tuple Complex type (again!) (9, false, 5.35) ! "###$###$########% & 9 & 0 & 5.35 & '###(###(########) 4 + 4 + 8 = 16 bytes
  57. 57. ● しない ● Garbage collection: runtime overhead ● Reference counting: memory (and operation) overhead ● Handling memory fragment
 ● ユースケース: そこまでは必要ない Memory freeing
  58. 58. もう1回DEMO kouのリポジトリでも⾒れます!
 https://github.com/utatti/kou
  59. 59. ● AssemblyScript ● https://assemblyscript.org ● A TypeScript to WebAssembly compiler
 ● WebAssembly Studio ● https://webassembly.studio Wasm Code gen. tip
  60. 60. つづく
  61. 61. 後編 LINEでの実践について @kawasako より
  62. 62. FRONT-END STANDARDIZATION 組織横断的にフロントエンド開発を標準化する
  63. 63. IN 技術調査/実践 内製ツール開発 OUT OSS活動 技術イベント協賛 イベント運営 ブログ執筆 LINE の Front-end Standardization Team における標準化とは WHAT IS STANDARDIZATION 社内だけでやっていること 社内でできていないこと 社内の均⼀化 × 社内外がシームレスな組織になること ○
  64. 64. 本題 WASMをどう使っていくか?
  65. 65. ⼤量の演算が必要な時
  66. 66. UIの利⽤状況をヒートマップ形式で可視化するツール YAKIMOCHI
  67. 67. [{"x":0,"y":55,"value":42},{"x":0,"y":65,"value":36},{"x":0,"y":75,"value":17},{"x": 0,"y":85,"value":25},{"x":0,"y":95,"value":31},{"x":0,"y":105,"value":19},{"x":0,"y": 115,"value":27},{"x":0,"y":125,"value":41},{"x":0,"y":135,"value":30},{"x":0,"y": 145,"value":33},{"x":0,"y":155,"value":44},{"x":0,"y":165,"value":58},{"x":0,"y": 175,"value":91},{"x":0,"y":185,"value":64},{"x":0,"y":195,"value":97},{"x":0,"y": 205,"value":81},{"x":0,"y":215,"value":249},{"x":0,"y":225,"value":103},{"x":0,"y": 235,"value":114},{"x":0,"y":245,"value":63},{"x":0,"y":255,"value":64},{"x":0,"y": 265,"value":79},{"x":0,"y":275,"value":26},{"x":0,"y":285,"value":33},{"x":0,"y": 295,"value":9},{"x":0,"y":305,"value":29},{"x":0,"y":315,"value":6},{"x":0,"y": 325,"value":20},{"x":0,"y":335,"value":8},{"x":0,"y":345,"value":8},{"x":0,"y": 355,"value":38},{"x":0,"y":365,"value":19},{"x":0,"y":375,"value":5},{"x":0,"y": 385,"value":13},{"x":0,"y":395,"value":27},{"x":0,"y":405,"value":20},{"x":0,"y": 415,"value":8},{"x":0,"y":425,"value":19},{"x":0,"y":435,"value":7},{"x":0,"y": 445,"value":181},{"x":0,"y":455,"value":23},{"x":0,"y":465,"value":16},{"x":0,"y": 475,"value":29},{"x":0,"y":485,"value":63},{"x":0,"y":495,"value":34},{"x":0,"y": 505,"value":24},{"x":0,"y":515,"value":8},{"x":0,"y":525,"value":35},{"x":0,"y": 画⾯に対して⼤量のデータが必要 解決したい課題 mb単位のデータがカジュアルに通信されてしまう = 遅い
  68. 68. データ圧縮/解凍をWASM(kou)で実装
  69. 69. ENCODED DATA ENCODER / DECODER ENCODER (WASM) DECODER (WASM) RAW DATA API SERVER (NODE.JS) CLIENT (BROWSER) RAW DATA 圧縮された⼩さいデータ元データ 復元されたデータ
  70. 70. Step-1 やること pixel毎にどのくらいtapされているかというデータがたくさんある
  71. 71. Step-1 やること X: 4 Y: 1 VALUE: 5 ひとつひとつは x座標, y座標, その座標のtap数のデータ
  72. 72. Step-1 やること X: 4 Y: 1 VALUE: 5 もしXとYを省略できればデータ量は1/3にできる
  73. 73. Step-2 やること 実はX,Yの座標は⾏列に変換すると必要なくなる 5 4px, 1px
 value: 5 4px 1px
  74. 74. Step-2 やること そのデータが何番⽬にあるかで座標がわかる 2x3の場合は12番⽬のデータになる 5 1 2px, 3px value: 1 2px 3px
  75. 75. Step-2 やること データを⾏列に埋めていくとデータの⼊らない場所ができる 0 1 2 3 5 5 6 7 8 9 10 1 12 13 14 15 16 17 18 19 20 21 22 23 24
  76. 76. Step-3 やること 連続したデータは何回連続するかという情報に変換して詰めちゃう(圧縮しちゃう) *4 5 *6 1 *2 14 *4 19 21*1 *3
  77. 77. Step-4 やること この⼩さいデータをブラウザで受け取って逆の処理をする (decode) 0 1 2 3 5 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 圧縮済データ ⾏列データ 元データ
  78. 78. の場合 WAT 全662⾏ 半年ほど前にflood-fillという簡単なアルゴリズムを実装したが苦⾏だった..
  79. 79. の場合 kou 全79⾏
  80. 80. let zip = fn (a [int], col int, row int) ([int], int) { ~ 中略 ~ while (i < l) { if (a[i - 1] == a[i]) { ct = ct + 1; } else { res = next(res, a[i - 1], ct); ct = 0; }; if (i == l - 1) { res = next(res, a[i], ct); } else {}; i = i + 1; }; ~ 中略 ~ res } の場合 kou JSerであれば直感的に書ける
  81. 81. 成果 じゃんじゃかじゃん
  82. 82. すごい 成果 約1/5まで圧縮 encode処理もJSで書くよりも3-4倍⾼速 1.4mb > 255kb
  83. 83. ● ⾼階層な⾔語ではないので中で何をやっているかは想像しやすい ● わからなくても作者が近くにいたので最強になれる ● それは普段あまりない経験
 ● wat書くよりはるかに楽で感動すら覚える ● しかしlog関数がないのはしんどい (⾃分で追加しようとした) ● 型の問題があってちゃんとやろうとするとそこそこ⼤変
 ● 全てがUint32Array問題 ● ⼤きな動画や画像データなど扱いたい時メモリを⾷いすぎる ● wasm使いたいモチベーションと相反する
 ● いつも⽂句いいながら書いてたけどJavaScriptって便利だな...なんでもあるやんけ... 所感 kou
  84. 84. ● LINEでは実験的な社内プロダクトがいくつかありその中では様々な挑戦をしている ● wasmもその中のひとつ
 ● wasmを直接触ることになるエンジニアの数は少ないと思う ● しかし、間違いなくライブラリやフレームワークで利⽤することになる
 ● 今後こんなことができるようになるかも と可能性を⾒据えて置くことは⼤事 ● 「これって実現可能なの?」を判断するのは開発者の⼤事な仕事
 ● それはwasmで⾔えば今まで扱えなかったような巨⼤なデータや処理を扱うことだっ たりするかもしれない webp, webm ⾔いたいこと⾔う まとめ
  85. 85. THANK YOU

×