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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
2.9k
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
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
150
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
340
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
1.3k
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
1k
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
7k
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
110
AmebaブログはKMPから卒業します
kmars0605
0
240
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
210
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
11
8k
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
3
540
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
220
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
1.8k
Featured
See All Featured
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1.1k
Raft: Consensus for Rubyists
vanstee
143
7.8k
Ethics towards AI in product and experience design
skipperchong
2
440
Crafting Experiences
bethany
1
390
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
900
Mind Mapping
helmedeiros
1
410
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.5k
My Coaching Mixtape
mlcsv
0
360
WCS-LA-2024
lcolladotor
0
920
HDC tutorial
michielstock
2
980
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
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ʣ
ʹΑͬͯҰ෦ͷλεΫ͕ܶతʹߴ Խ͢ΔՄೳੑ͋Γ