Slide 1

Slide 1 text

© 2012-2023 BASE, Inc. 1 PHPerKaigi 2023 BASE株式会社 永野 峻輔 ( @glassmonekey ) PHPをブラウザで動かす技術

Slide 2

Slide 2 text

© 2012-2023 BASE, Inc. 2 @glassmonekey #phperkaigi このトークの目的 ● WebAssembly (Wasm) の基本的な理解 ● PHPをブラウザ動かすための仕組みを理解

Slide 3

Slide 3 text

© 2012-2023 BASE, Inc. 3 @glassmonekey #phperkaigi 自己紹介 所属 BASE 株式会社 BASE BANKチーム Engineering Program Manager 資金調達プロダクト「YELL BANK」の開発責任者やってます。 Go, PHP, Pythonを書きつつ時々データエンジニアも。 趣味 個人開発 最近は日帰り温泉とかも   SNS Twitter: @glassmonekey  Github: https://github.com/glassmonkey 永野 峻輔 (ながの しゅんすけ) 去年のPHP Conferenceにて

Slide 4

Slide 4 text

© 2012-2023 BASE, Inc. 4 1 2 3 @glassmonekey #phperkaigi Wasmとは ブラウザでPHPを動作するデモ PHPを動作させるための技術について 今日話すこと

Slide 5

Slide 5 text

© 2012-2023 BASE, Inc. 5 Wasm とは

Slide 6

Slide 6 text

© 2012-2023 BASE, Inc. 6 @glassmonekey #phperkaigi Wasmとは Webブラウザを含む実行環境で コード実行とコンパクトなコード表現を実現するバイナリ形式 https://developer.mozilla.org/ja/docs/WebAssembly/Concepts

Slide 7

Slide 7 text

© 2012-2023 BASE, Inc. 7 @glassmonekey #phperkaigi 対応状況 https://developer.mozilla.org/ja/docs/WebAssembly モダンな環境なら基本動く

Slide 8

Slide 8 text

© 2012-2023 BASE, Inc. 8 @glassmonekey #phperkaigi 例 (webassembly.sh) Linuxを模倣したもの https://webassembly.sh

Slide 9

Slide 9 text

© 2012-2023 BASE, Inc. 9 なぜ Wasm なのか

Slide 10

Slide 10 text

© 2012-2023 BASE, Inc. 10 @glassmonekey #phperkaigi Webアプリのリッチ化

Slide 11

Slide 11 text

© 2012-2023 BASE, Inc. 11 @glassmonekey #phperkaigi JavaScriptだけだと辛い ● ブラウザゲーム(特に3D) ● AR/VR ● 画像処理 … etc

Slide 12

Slide 12 text

© 2012-2023 BASE, Inc. 12 @glassmonekey #phperkaigi JavaScript + Wasm WebAssembly: How and why https://blog.logrocket.com/webassembly-how-and-why-559b7f96cd71/ WASMはJSの一部の代替え

Slide 13

Slide 13 text

© 2012-2023 BASE, Inc. 13 @glassmonekey #phperkaigi 導入事例から見るWasm https://madewithwebassembly.com/

Slide 14

Slide 14 text

© 2012-2023 BASE, Inc. 14 @glassmonekey #phperkaigi Figma ● パフォーマンス向上 (約3倍) ● もともとはasm.js (C++からコンパイルしたJS)をつかっていた https://www.figma.com/blog/webassembly-cut-figmas-load-time-by-3x/

Slide 15

Slide 15 text

© 2012-2023 BASE, Inc. 15 @glassmonekey #phperkaigi 1Password ● 入力解析部分で主な改善 ● Chromeで最大13倍、Firefoxだと39倍  https://blog.1password.com/1password-x-may-2019-update/

Slide 16

Slide 16 text

© 2012-2023 BASE, Inc. 16 @glassmonekey #phperkaigi TensorFlow ● パフォーマンス向上(約10倍) ● 機械学習のようなCPUなどのリソースを酷使する場合とは相性が良い https://yashints.dev/blog/2019/12/17/tfjs-wasm

Slide 17

Slide 17 text

© 2012-2023 BASE, Inc. 17 Wasmの特徴

Slide 18

Slide 18 text

© 2012-2023 BASE, Inc. 18 @glassmonekey #phperkaigi Web Assemblyとは(2回目) Webブラウザを含む実行環境で コード実行とコンパクトなコード表現を実現するバイナリ形式 https://developer.mozilla.org/ja/docs/WebAssembly/Concepts

Slide 19

Slide 19 text

© 2012-2023 BASE, Inc. 19 @glassmonekey #phperkaigi Wasmの特徴 ● 移植性 ○ 任意の言語でWebAssemblyにbuildできたら良い ● セキュア ○ Runtimeが隔離(Sandbox化)されているのでセキュア WASM Host System WASI API WASM Runtime

Slide 20

Slide 20 text

© 2012-2023 BASE, Inc. 20 @glassmonekey #phperkaigi Wasmと仕様 ● 基本仕様 ○ WASM-Core ● ブラウザ用仕様 ○ WASM Web API ○ WASM JS API ● ブラウザ外仕様 ○ WASI (Web Assembly System Interface) https://webassembly.org/specs/ それぞれ別物!!

Slide 21

Slide 21 text

© 2012-2023 BASE, Inc. 21 @glassmonekey #phperkaigi WASI(Web Assembly System Interface) 任意のシステムで呼び出すための仕様 ● 汎用的なランタイムとして活用 ○ ex) Wasmer, Wasmtime, Cranelift, WAMR ● Edgeコンピューティングでの活用 ○ ex) CloudflareWorkers (Cloudflare), Compute@Edge (Fastly) ● K8sでの活用 ○ ex) proxy-wasm 詳しくは https://bytecodealliance.org/ WASM Host System WASI API WASM Runtime

Slide 22

Slide 22 text

© 2012-2023 BASE, Inc. 22 PHPをブラウザで動かす

Slide 23

Slide 23 text

© 2012-2023 BASE, Inc. 23 @glassmonekey #phperkaigi デモ (https://php-play.dev) デモページ

Slide 24

Slide 24 text

© 2012-2023 BASE, Inc. 24 @glassmonekey #phperkaigi デモのスペック https://php-play.dev ● リアルタイムPHP Playground ● React製 ● Github Pagesでhosting ● PHP 5.6 ~ 8.2のWasmを切り替え可能に ● Wordpress/playground から ビルドスクリプトなどをvendoringしている

Slide 25

Slide 25 text

© 2012-2023 BASE, Inc. 25 @glassmonekey #phperkaigi Wordpress/Playground https://developer.wordpress.org/playground/ ● WordpressをWasmで動くようにしたもの。 ● Iframeで展開される ● サービスワーカーがリクエストをインターセプト ● npmパッケージが公開されるらしい ?

Slide 26

Slide 26 text

© 2012-2023 BASE, Inc. 26 @glassmonekey #phperkaigi コード抜粋

Slide 27

Slide 27 text

© 2012-2023 BASE, Inc. 27 @glassmonekey #phperkaigi 動作内容(一部抜粋) ● initPHPでWasmモジュールを準備 ● runPHPで任意のPHPコードを 実行できるように ● startPHPなどはWordpress/playground からvendoringしたもの

Slide 28

Slide 28 text

© 2012-2023 BASE, Inc. 28 @glassmonekey #phperkaigi 動作内容イメージ(プレビュー部分) ● usePHPで任意のPHPコードを実行 ● 結果をiframeで展開 ○ sandbox属性でXSS対策

Slide 29

Slide 29 text

© 2012-2023 BASE, Inc. 29 @glassmonekey #phperkaigi 動作内容イメージ(カスタムHook) ● PHPコードの状態管理 ○ 選択中のPHPランタイム ○ プレビュー用のコード ○ プレビュー結果 ○ 実行中か ● startPHPでPHPRuntimeのバージョン選択 ● runPHPで任意のPHPコードの実行 ○ 例えば phpinfo(); のようなコード

Slide 30

Slide 30 text

© 2012-2023 BASE, Inc. 30 @glassmonekey #phperkaigi その他秘話について https://zenn.dev/glassmonkey/articles/ae6cadef80c6c4

Slide 31

Slide 31 text

© 2012-2023 BASE, Inc. 31 @glassmonekey #phperkaigi 再掲 https://php-play.dev

Slide 32

Slide 32 text

© 2012-2023 BASE, Inc. 32 @glassmonekey #phperkaigi GitHub Pagesで動くPHP!!

Slide 33

Slide 33 text

© 2012-2023 BASE, Inc. 33 PHPをブラウザで呼び出す技術

Slide 34

Slide 34 text

© 2012-2023 BASE, Inc. 34 @glassmonekey #phperkaigi PHPをブラウザで呼び出すためには ● PHPをWasm用にコンパイル ● WasmをJavaScriptから呼び出す

Slide 35

Slide 35 text

© 2012-2023 BASE, Inc. 35 @glassmonekey #phperkaigi PHPをブラウザで呼び出すためには ● PHPをWasm用にコンパイル ● WasmをJavaScriptから呼び出す

Slide 36

Slide 36 text

© 2012-2023 BASE, Inc. 36 @glassmonekey #phperkaigi PHPは何言語でかれているか?

Slide 37

Slide 37 text

© 2012-2023 BASE, Inc. 37 @glassmonekey #phperkaigi C言語

Slide 38

Slide 38 text

© 2012-2023 BASE, Inc. 38 @glassmonekey #phperkaigi コンパイルの方針 ● 基本的にはPHPのソースを流用する ● 一部Wasm用に書き換える ● C言語のコンパイラを利用する

Slide 39

Slide 39 text

© 2012-2023 BASE, Inc. 39 @glassmonekey #phperkaigi emscripten https://emscripten.org/ ● C/C++をWasmにコンパイルできる ● ブラウザなどのRuntimeで実行可能にする ● LLVM/Clangベースのコンパイラ

Slide 40

Slide 40 text

© 2012-2023 BASE, Inc. 40 @glassmonekey #phperkaigi emscriptenの利用例(C++) ● C++で書いたのでC++かCかどうかの 判定マクロが必要 ● 今回の例では以下の関数を Wasmへの変換時にexport ○ main関数 ○ EMSCRIPTEN_KEEPALIVE でアノテーションした関数 https://github.com/glassmonkey/wasm-sample-cpp https://developer.mozilla.org/ja/docs/WebAssembly/C_to_wasm

Slide 41

Slide 41 text

© 2012-2023 BASE, Inc. 41 @glassmonekey #phperkaigi emscriptenの利用例 (呼び出し) ● グルーコードも同時に生成される ● Wasmロード時にmain関数が実行完了しても Runtimeが終了しないように ● ccallというメソッドで呼び出し可能に ● exportした関数の呼び出し https://github.com/glassmonkey/wasm-sample-cpp https://developer.mozilla.org/ja/docs/WebAssembly/C_to_wasm JSからの呼び出し コンパイル

Slide 42

Slide 42 text

© 2012-2023 BASE, Inc. 42 @glassmonekey #phperkaigi 準備は整った

Slide 43

Slide 43 text

© 2012-2023 BASE, Inc. 43 @glassmonekey #phperkaigi PHPをWasm用にコンパイル

Slide 44

Slide 44 text

© 2012-2023 BASE, Inc. 44 @glassmonekey #phperkaigi PHPをWasm用にコンパイル = エントリーポイントの作成 + Patchを当てる

Slide 45

Slide 45 text

© 2012-2023 BASE, Inc. 45 @glassmonekey #phperkaigi エントリーポイントの作成 ● PHP本体を呼びつつ、JSから呼び出せるよう にしている ● zend_eval_stringを呼び出している。

Slide 46

Slide 46 text

© 2012-2023 BASE, Inc. 46 @glassmonekey #phperkaigi Patchを当てる例(その1) 常にPDOをbuildに含めるようにしたり

Slide 47

Slide 47 text

© 2012-2023 BASE, Inc. 47 @glassmonekey #phperkaigi Patchを当てる例(その1) 空ファイルをfile_get_contentsでJS経由で 可能にしたり

Slide 48

Slide 48 text

© 2012-2023 BASE, Inc. 48 @glassmonekey #phperkaigi (余談)Patch内容の起源 https://github.com/oraoto/pib/pull/52 大半の修正内容の詳細が不明 Wasm製PlayGroundへのPRが起源 https://oraoto.github.io/pib/ 当てなくてもいい部分はあるかもしれない。

Slide 49

Slide 49 text

© 2012-2023 BASE, Inc. 49 @glassmonekey #phperkaigi PHPをブラウザで呼び出すためには ● PHPをWasm用にコンパイル ● WasmをJavaScriptから呼び出す

Slide 50

Slide 50 text

© 2012-2023 BASE, Inc. 50 @glassmonekey #phperkaigi 動作内容(一部抜粋、再掲) ● initPHPでWasmモジュールを準備 ● runPHPで任意のPHPコードを 実行できるように ● runPHPで任意のPHPコードを 実行できるように ● runPHPで任意のPHPコードを 実行できるように ● runPHPで任意のPHPコードを 実行できるように ● startPHPなどはWordpress/playground からvendoringしたもの

Slide 51

Slide 51 text

© 2012-2023 BASE, Inc. 51 @glassmonekey #phperkaigi PHPオブジェクトの中身 ● Runtimeはコンパイラ経由のグルーコード が該当する。 ● setPHPCodeとhandleRequstが肝 ?>を先頭につけることで、 前回実行したPHPコードを終了させてい る

Slide 52

Slide 52 text

© 2012-2023 BASE, Inc. 52 @glassmonekey #phperkaigi Wasm関数の呼び出し ● ccallでC側で定義した各種関数をコールしている ● Wasm上のファイルシステム経由で結果を取得 ● ファイルシステム(一部抜粋) ○ MEMFS(デフォルト) ■ いわゆるオンメモリ。リロードで消える ○ NODEFS ■ nodejsで使用するとき(ローカルで永続化) ○ IDBFS ■ ブラウザのIndexedDBを使用する などなど https://emscripten.org/docs/api_reference/Filesystem-API.html#file-s ystems

Slide 53

Slide 53 text

© 2012-2023 BASE, Inc. 53 @glassmonekey #phperkaigi C言語側との対応

Slide 54

Slide 54 text

© 2012-2023 BASE, Inc. 54 まとめ

Slide 55

Slide 55 text

© 2012-2023 BASE, Inc. 55 @glassmonekey #phperkaigi まとめ ブラウザ上でもPHPは動く

Slide 56

Slide 56 text

© 2012-2023 BASE, Inc. 56 @glassmonekey #phperkaigi まとめ Wasmと仲良くなりましょう

Slide 57

Slide 57 text

© 2012-2023 BASE, Inc. 57 @glassmonekey #phperkaigi まとめ ● WasmはWebアプリのリッチ化で始まった技術 ● PHPはブラウザでも呼び出し可能 ○ 永続化方法がブラウザベースだと課題感あり ○ CloudflareのD1あたりとの組み合わせの可能性はありそう ○ Playgroundレベルだと実用性あり。ぜひ使ってね!! ● PHPのソースコード読むことは楽しい ● Wasmの動向は要チェック

Slide 58

Slide 58 text

© 2012-2023 BASE, Inc. 58 宣伝

Slide 59

Slide 59 text

© 2012-2022 BASE, Inc. 59 #phperkaigi @glassmonkey https://kyloz.wraptas.site/ 個人開発!!

Slide 60

Slide 60 text

© 2012-2022 BASE, Inc. 60 #phperkaigi @glassmonkey フルサイクル開発やってます!! Go, Pythonも書いてます!! DM待ってます!! We are hiring !!