Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
AssemblyScriptでライブラリコードの高速化をしてみる
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
FUJI Goro
July 24, 2019
Programming
3.4k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AssemblyScriptでライブラリコードの高速化をしてみる
FUJI Goro
July 24, 2019
More Decks by FUJI Goro
See All by FUJI Goro
ステートレスなLLMでステートフルなAI agentを作る - YAPC::Fukuoka 2025
gfx
7
2.1k
How to Boost Your Code with WebAssembly
gfx
2
3.2k
実践TypeScriptトークバトル
gfx
1
1.3k
歴史的経緯の説明 as code
gfx
7
3k
Elasticsearchによる 全文検索の実装 in Rails
gfx
6
9.9k
すばらしきGraphQLのSEKAIへようこそ
gfx
20
10k
マルチテナント・ウェブアプリケーションの実践
gfx
14
9.9k
How to choose the ORM on Android
gfx
1
4.5k
How Do We Get Along With Static Types
gfx
5
3.5k
Other Decks in Programming
See All in Programming
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
170
Web Framework Benchmark Battle 2026, Any%
a_matsuda
3
3.2k
AWS CDKを理解するために公式の定義を深掘って解説してみる / Understanding AWS CDK by Digging into Its Official Definition
akihisaikeda
3
290
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
230
[DroidKnights 2026] Workflow AX: From Auto-Documented Policies to E2E Testing
raeminkang
0
560
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
1.9k
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
220
まずはコードより業務と向き合う:テーブル解体のためにPdMを呼んだ話
sakawe_ee
0
210
LLM 101
dalinaum
0
480
AIがコードを書いてくれる時代、我々は何を確かめるのか
yosuke_furukawa
PRO
13
5.9k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
300
Getting Started with Vibe Coding
miccheng
0
200
Featured
See All Featured
It's Worth the Effort
3n
188
29k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.4k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
520
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
31k
What's in a price? How to price your products and services
michaelherold
247
13k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
エンジニアに許された特別な時間の終わり
watany
109
250k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
2
3.8k
Making Projects Easy
brettharned
120
6.9k
Transcript
AssemblyScriptͰϥΠϒϥϦ ίʔυͷߴԽΛͯ͠ΈΔ Emscripten & WebAssembly night!! #8 In Mercari, Inc.
,2019/07/24 by FUJI Goro (@__gfx__)
ࣗݾհ • FUJI Goro / @__gfx__ • ϑϩϯτΤϯυͱ͔Web APIͱ͔ •
࠷͍ۙͯ͠Δٕज़GraphQLͱ TypeScriptͱWebAssembly
WebAssembly as a universal executable binary • Φϓτϐ: WebAssemblyʹϢχόʔαϧͳόΠφϦͱ ͯ͠ظͯ͠Δ
• ͭ·ΓϓϥοτϑΥʔϜඇґଘͳόΠτίʔυ • ࢼ͠ʹzopfli (C library) ΛwasmʹϏϧυͯ͠ @gfx/ zopfli ͱͯͯ͠͠Έͨ • native binding൛ΑΓ͍͕Πϯείָ͕ͳͷͰͦ͜ ͦ͜ΘΕΔΑ͏ʹͳͬͨ
WASM in intereters • কདྷతʹRuby / Perl / Python ͱ͍ͬͨΠϯλϓϦλ͕
WASM࣮ߦΤϯδϯΛ࣋ͭΑ͏ʹͳΔͷͰͳ͍͔ • ͜ͷํͰͷࢼΈ͕wasmerͰɺ͢Ͱʹϝδϟʔͳݴޠ༻ͷ binding͕͋Δ • WASM͕ϏϧυࡁΈόΠφϦͷϑΥʔϚοτͱͯ͠ϝ δϟʔʹͳΔͱ͍͍ͳ͋…ͱࢥ͍ͬͯΔ • ߴͳwasmॲཧܥඞཁʢwasmer͕Ͳ͏͔ະௐࠪʣ
ؓٳ
WebAssemblyͷ༻్ • طଘͷ C / C++ / Rust / Go
ΛJSʹίϯύΠϧ ͢Δ • ͦΕͳΓʹ҆ఆ͍ͯͯ͠ී௨ʹศར • ৽͍͠ͷҰ෦ΛWebAsemblyͰߴԽ͢Δ • ࠓճͬͪ͜ • ͜ͷ༻్ͷύϑΥʔϚϯεະͰʁʁ
ͬͯΈͨ
ݴޠ: AssemblyScript • બࢶͱͯ͠ C / C++ / Rust /
Go / AssemblyScript • ࠓճϥϯλΠϜ͕Ұ൪খͦ͞͏ͳ AssemblyScriptΛબ • ʢଞͷݴޠࢼ͔͕ͨͬͨؒ͠ʹ߹Θͣʣ
AssemblyScript • TypeScriptͷαϒηοτΛߏจͱͯ͠ར༻ͨ͠શ͘ ৽͍͠ϓϩάϥϛϯάݴޠ • ॻ͖ຯTypeScriptΑΓC/C++ʹ͍ۙ • ͱ͍͏͔TypeScriptͷൽ͚ͩͯ͠தΛ͘Γൈ ͍ͯC/C++Λ٧Ίͨ͠ݴޠͱ͍͏͖ •
ͨͩ͠CΑΓଟػೳɺC++ΑΓශऑ
AssemblyScriptͷ࠷దԽث • AssemblyScriptͷόοΫΤϯυBynarien • Emscripten͕Β͖࣮ͬͯͨ͘ͷ͋Δόο ΫΤϯυ • ʢ͍·EmscriptenLLVM backendਪ͠ʣ •
খ͞ͳؔͷΠϯϥΠϯԽͳͲɺجຊతͳ࠷ద ԽBynarien͕ͬͯ͘ΕΔ
ςʔϚ: MessagePack codec • ͦͦWebAssemblyόΠτྻ (ArrayBuffer) ͔͠ѻ͑ͳ͍ͷͰɺಘҙ ݶΒΕͦ͏ • खݩͷίʔυͩͱMessagePackόΠφϦγ
ϦΞϥΠβͳͷͰWASMͰߴԽͷ༨͋ Γͦ͏ͩͱ౿Μͩ
ϦϙδτϦ • https://github.com/msgpack/msgpack-javascript • v1.6.0 ݱࡏͷ • npm install @msgpack/msgpack
ͰΠϯείՄೳ • ͨͩ͠WASM൛ݱࡏweb൛ͰΘΕͳ͍Α͏ʹͳͬ ͍ͯΔ • WASM·ΘΓͷίʔυ͍ͣΕফͨ͠ΓRustʹॻ͖͑ͨ Γ͢Δ͔
࣮ • MessagePack decoderͷҰ෦ɺจࣈྻͷσ ίʔυΛJS / WASM (AS) / ωΠςΟϒίʔυ
ͦΕͧΕͰ࣮ͨ͠ • ͍ͬͯΔ͜ͱUTF-8ͷྻΛUTF-16ͷ ྻʹม͢Δ͜ͱ • AssemblyScriptʹҠ২ͯ͠100ߦఔ
JS൛ͷίʔυʢൈਮʣ export function utf8DecodeJs(bytes: Uint8Array, inputOffset: numbe byteLength: number): string
{ let offset = inputOffset; const end = offset + byteLength; const units: Array<number> = []; while (offset < end) { const byte1 = bytes[offset++]; if ((byte1 & 0x80) === 0) { // 1 byte units.push(byte1); } // ... } return String.fromCharCode(...units); }
ωΠςΟϒίʔυ൛ͷίʔυ const sharedTextDecoder = new TextDecoder(); export function utf8DecodeTD(bytes: Uint8Array,
inputOffset: numbe byteLength: number): string { const stringBytes = bytes.subarray(inputOffset, inputOffset + byteLength); return sharedTextDecoder!.decode(stringBytes); }
AS൛ͷίʔυʢൈਮ, AS 0.6ʣ export function utf8DecodeToUint16Array(outputPtr: usize, inputPtr: usize, byteLength:
usize): usize { let inputOffset = inputPtr; let outputOffset = outputPtr; let inputOffsetEnd = inputOffset + byteLength; const u16s = sizeof<u16>(); while (inputOffset < inputOffsetEnd) { let byte1: u16 = load<u8>(inputOffset++); if ((byte1 & 0x80) === 0) { // 1 byte store<u16>(outputOffset, byte1); outputOffset += u16s; } } return (outputOffset - outputPtr) / u16s; }
AS൛ͷίʔυʢJSଆʣ // wm = InstantiatedWasmModule.exports type pointer = number; //
32-bit integer export function utf8DecodeWasm(bytes: Uint8Array, inputOffset: numbe byteLength: number): string { const inputPtr: pointer = wm.malloc(byteLength); const outputPtr: pointer = wm.malloc(byteLength * 2); try { setMemoryU8(inputPtr, bytes.subarray(inputOffset, inputOffset + byteLength), byteLength); const outputArraySize = wm.utf8DecodeToUint16Array(outputPtr, inputPtr, byteLength); const units = new Uint16Array(wm.memory.buffer, outputPtr, outputArraySize); return String.fromCharCode(...units); } finally { wm.free(inputPtr); wm.free(outputPtr); } }
WASM functionͷೖྗ • WASMʹͤΔ2छྨ • (1) WASM functionͷݺͼग़͠ͷҾͱͯ͠ɺҙݸͷ·ͨුಈখ •
(2) WASM moduleͷbuffer: ArrayBufferʹΛॻ͖ࠐΉɻArrayBufferʹॻ ͖ࠐΊΔͳΒͳΜͰOK • Ͳ͜ʹॻ͖ࠐΜ͔ͩͷoffsetΛ(1)ͷҾͱͯ͢͠ • Cݴޠతʹݴ͑͜Ε͕ϙΠϯλ • ASͰ load<T>(offset) ؔͰಡΈग़ͤΔ
WASM function͔Βͷग़ྗ • ·ͨුಈখ1͚ͭͩ • ʢWASMతʹҙͷͷΛฦͤΔ͕ʣ • ࠓճೖྗͱͯ͠outputPtr (offset) Λ͠ɺ
WASM functionग़ྗΛoutputPtrͷҐஔʹ ॻ͖ࠐΈɺॻ͖ࠐΜͩαΠζΛWASM function ͔Βฦ͢ͱ͍͏͜ͱʹͨ͠
WASM functionͷγάωνϟ • ίϝϯτ͖ͭͰ࠶ܝ͢Δͱɺ͜Μͳײ͡ export function utf8DecodeToUint16Array( outputPtr: usize, //
output offset inputPtr: usize, // input offset byteLength: usize, // input length ): usize; // output length
AS (0.6) ͷϋϚΓͲ͜Ζ • ϙΠϯλܕ͕ͳͯ͘͢ usize (uint32_t) ܕ • load<u16>()
/ store<u16>() ͳͲϦτϧΤϯσΟΞϯͱنఆ ͞Ε͍ͯΔ͕ɺJSଆͷtyped arrays (Uint16Array) ϗετͷΤ ϯσΟΞϯͳͷͰຊޓੑ͕ͳ͍ • ͔͠͠ɺ͖ΐ͏ͼͷϚγϯϦτϧΤϯσΟΞϯͳͷͰಈ͍ ͯ͠·͏ʢASͷͰͳ͍͕ʣ • ݟ͕ͨTypeScriptͳ͜ͱʹؾ͕࣋ͪҾ͖ͣΒΕͯຌϛε͕සൃ ͢Δ
AS (0.7) ͷϋϚΓͲ͜Ζ • ͳ͓ݱߦόʔδϣϯ (0.7) ϦϑΝϨϯεΧ ϯτϥϯλΠϜ͕Ճ͞ΕͨͷͰJSͱͷ૬ޓ ӡ༻͕ΑΓ͘͠ͳͬͨ •
msgpack-javascript·ͩAS 0.7ʹରԠͰ͖ ͍ͯͳ͍ɺͱ͍͏͔͍ͬͦASΛࣺͯͯRust ʹ͠Α͏ͱࢥ͍ͬͯΔ
ϕϯνϚʔΫ
ڥ • macOS 10.14 • NodeJS 12.6.0 • v8 7.5
ʢChrome 75૬ʣ • ࠓճNodeJSͷΈͰϕϯνϚʔΫΛͨ͠
ϕϯνϚʔΫίʔυ • https://gist.github.com/gfx/ e3e33c80848f734a81dbd030fca16230 • “A”.repeat(N) ʢNσʔλαΠζʣͱ͍͏ σʔλΛUTF-8Τϯίʔυͨ͠όΠτྻΛɺ JS൛ /
WASM൛ / ωΠςΟϒίʔυ൛ͷؔ Ͱจࣈྻʹσίʔυ͢Δ
νϟʔτͷݟํ • ॎ࣠ log10 (ops per sec) • ͦͷ··ͩͱݟͮΒ͍ͷͰରʹͯ͋͠Δ •
͕େ͖͍΄Ͳੑೳ͕Α͍ • ԣ࣠σʔλαΠζ • ಉ͡σʔλαΠζಉ࢜Ͱൺֱ͢Δ͜ͱ • σʔλαΠζ͕ҟͳΔσʔλͷൺֱແҙຯ
ϕϯνϚʔΫ݁Ռ 0 2 4 6 8 10 100 200 500
1000 10000 utf8DecodeJs utf8DecodeWasm TextDecoder default, NodeJS/v12.6.0, v8/7.5
νϟʔτ͔ΒಡΈऔΕΔ͜ͱ • σʔλαΠζ͕খ͍͞ͱ͖JS൛͕࠷ • WASM൛ / ωΠςΟϒίʔυ൛ॲཧࣗମߴ ͕ͩݺͼग़͠ͷΦʔόʔϔου͕େ͖͍ͨΊ • σʔλαΠζ͕େ͖͘ͳΔͱ
ωΠςΟϒίʔυ൛ >> WASM൛ > JS൛ • ͦͦJS൛ͱWASM൛ͰͦΕ΄Ͳࠩͳ͍
JS൛ͱWASM൛ͷ͕ࠩͳ͍ʁʁ • ͔֬ʹσʔλαΠζ͕େ͖͘ͳΔͱWASM൛ͷ΄͏͕গͩ͠ ͚ͱ͍ܾ͑ఆతʹ͍ • ͔ͦ͠͠ͷ͍͍ࠩͤͥे%Ͱɺ։ൃΛߟ͑ΔͱWASM ൛ίεύ͕ѱ͍ • AssemblyScript͕ͭΒ͍ͱ͍͏͜ͱ͋Δ͕ɺͦͦݴޠ Λ·͍ͨͩϒϦοδΛϝϯς͢Δͷٕज़తͳқ͕ߴ͍
• ݁ہɺV8ͷ࠷దԽJITίϯύΠϥ͕ڧ͗͢ΔͷͰ͍JSίʔυ ͷॻ͖ํΛֶͿͷ͕ίεύ͕Α͍
ୈҰ෦
ୈೋ෦
~ v8 —no-opt ฤ ~
V8ͷΞʔΩςΫνϟ(2017)
࠷దԽJITίϯύΠϥ TurboFan • ͔ͨ͠ʹV8TurboFan͕ޮ͚ര • ͔͠͠ΣϒϖʔδͷॳճಡΈࠐΈ͔࣌Βૢ ࡞ՄೳʹͳΔ·ͰͷؒɺTurboFanʹΑΔ࠷ దԽ͕·ͩޮ͍ͯͳ͍͔͠Εͳ͍ • ͭ·ΓTurboFanͷੑೳΛଌΔϕϯνϚʔΫ͕
͋ͳͨͷέʔεʹద߹͢ΔͱݶΒͳ͍
v8 —no-opt • v8ͷ࠷దԽΛແޮʹ࣮ͯ͠ߦ͢ΔΦϓγϣϯ • nodejsͰ͜ͷΦϓγϣϯ͕͑Δ • ͜ͷΦϓγϣϯ͖ͰϕϯνϚʔΫΛ͢Δ ͱɺͨͱ͑ҰॠͰ࣮ߦΛऴ͑ΔίϚϯυϥ ΠϯπʔϧΣϒϖʔδͷॳظԽίʔυͷ
࣮ߦͳͲͷڥΛΤϛϡϨʔτͰ͖Δ
nodejs —no-opt Ͱ࠶ܭଌ
ϕϯνϚʔΫ݁Ռ (—no-opt) 0 2 4 6 8 10 100 200
500 1000 10000 utf8DecodeJs utf8DecodeWasm TextDecoder --no-opt NodeJS v12.6.0, v8 7.5 on macOS
ϕϯνϚʔΫ݁Ռ (default) 0 2 4 6 8 10 100 200
500 1000 10000 utf8DecodeJs utf8DecodeWasm TextDecoder default, NodeJS/v12.6.0, v8/7.5
νϟʔτ͔ΒಡΈऔΕΔ͜ͱ • ࠷దԽ͕ޮ͔ͳ͍ͱ͖͔ͳΓখ͍͞σʔλα ΠζͰ WASM൛ >> JS൛ • ࠷దԽ͕ޮ͍͍ͯͯWASM൛ͷ΄͏͕JS൛Α Γগ͍͠
• ىಈ࣌ͷϘτϧωοΫ͕WASMͷಘҙͦ͏ͳλ εΫͰ͋ΕWASMԽΛݕ౼ͯ͠Αͦ͞͏
·ͱΊ: ʮ·ͩૣ͍ʯ • ʮAssemblyScriptͰϥΠϒϥϦίʔυͷߴ ԽΛͯ͠ΈΔʯͷՄೳ͕ͩίεύѱ͍ • WASMJITʹΑΔ࠷దԽ͕ޮ͍͍ͯͳͯ͘ ͍ͷͰঢ়گʹΑͬͯޮՌ͋Γͦ͏ • WASMࣗମ͕·ͩख़͍ͯ͠ͳ͍ͷͰɺ݁
ͱͯ͠ʮ·ͩૣ͍ʯͱ͍͏͜ͱʹ͓ͯ͘͠
Appendix
ݺͼग़͠ͷΦʔόʔϔου • WASMݺͼग़͠ͷΦʔόʔϔουೖྗΛArrayBufferίϐʔ ͨ͠Γग़ྗΛArrayBuffer͔Βίϐʔͨ͠Γ͢Δͷ͕΄ͱΜͲ • ݱࡏWASMʹఏҊ͞Ε͍ͯΔ reference-types ɺanyrefͱ͍͏ ܕͰJSͷΦϒδΣΫτΛWASMʹͤΔΑ͏ʹͳΔ༷ •
anyrefࣗମԿૢ࡞Ͱ͖ͳ͍͕ͩɺ ͨͱ͑ࠓճͷ߹ WASM moduleʹରͯ͠ readU8FromUint8Array(u8array: anyref, offset: usize): u8 Έ͍ͨͳؔΛexport͢Δ͜ͱͰೖྗ ΛArrayBufferʹίϐʔͤͣʹࢀরͰ͖ΔΑ͏ʹͳΔʢͣʣ
ύϑΥʔϚϯεͷࠓޙ • WASMॴḨόΠτίʔυͳͷͰ࣮ߦ͕͜Ε͔ ΒܶతʹมΘΔͱ͍͏͜ͱͳͦ͞͏ • ͍·ωΠςΟϒίʔυͷ30%-50%΄Ͳͷ • ͨͩ͠ɺωΠςΟϒίʔυΛࣗ༝ʹ͑ͳ͍ڥ ʢϒϥβʣͰɺ͜Ε͔ΒWASMʹ͘Δػೳʢͨ ͱ͑SIMDʣ
ʹΑͬͯҰ෦ͷλεΫ͕ܶతʹߴ Խ͢ΔՄೳੑ͋Γ