Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Streams APIとTCPフロー制御 / Web Streams API and TCP ...
Search
tasshi
October 31, 2024
Programming
2
640
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
Nihonbashi.js #9 のLT資料です。
イベント情報はこちら↓
https://nihonbashi-js.connpass.com/event/332328/
tasshi
October 31, 2024
Tweet
Share
More Decks by tasshi
See All by tasshi
プロダクトにも、チームにも。サイボウズがAIと共に歩む理由 / YAPC 2025 Cybozu Team AI
tasshi
0
350
Web Streams APIの基本と実践、TypeScriptでの活用法 / TSKaigi 2025 Web Streams API
tasshi
6
2k
2024年のkintone API振り返りと2025年 / kintone API look back in 2024
tasshi
0
340
GitHub Projectsを自動化するGitHub CLIテクニック / Automate GitHub Projects with GitHub CLI
tasshi
2
1.9k
SDK開発チームのプロダクトオーナーが考えていること / Product management of SDK
tasshi
1
1.7k
Node.js製CLIツールのE2Eテストに取り組んでいます / Working on E2E testing of Node.js CLI tools
tasshi
0
1.6k
モダンな開発環境を用いた カンタン/安全なカスタマイズ開発 / kintone devCamp Boost! 2023
tasshi
0
950
Node Streamでメモリ性能改善、そしてWeb Streams APIへ / Improving memory performance of the CLI tool using Node Stream
tasshi
1
3.7k
グローバルチームことはじめ / Bootstrapping a global team
tasshi
1
4.3k
Other Decks in Programming
See All in Programming
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.6k
20251212 AI 時代的 Legacy Code 營救術 2025 WebConf
mouson
0
250
TerraformとStrands AgentsでAmazon Bedrock AgentCoreのSSO認証付きエージェントを量産しよう!
neruneruo
4
2.5k
ゆくKotlin くるRust
exoego
1
210
2年のAppleウォレットパス開発の振り返り
muno92
PRO
0
180
Deno Tunnel を使ってみた話
kamekyame
0
330
Denoのセキュリティに関する仕組みの紹介 (toranoana.deno #23)
uki00a
0
240
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
3
3.1k
AIエージェントの設計で注意するべきポイント6選
har1101
6
3.2k
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
170
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
2.2k
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
140
Featured
See All Featured
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
160
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.6k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.6k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
We Have a Design System, Now What?
morganepeng
54
8k
Building Adaptive Systems
keathley
44
2.9k
Making Projects Easy
brettharned
120
6.5k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
0
3.4k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
140
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Transcript
Streams APIと TCPフロー制御 2024.10.31 Nihonbashi.js #9 @tasshi_me 1
Stream APIとTCPフロー制御 - Nihonbashi.js #9 はじめに ⽥代雅治 (@tasshi_me) • 仕事
• サイボウズ株式会社 • kintone拡張基盤🧩チーム EM • 好きなもの • ⾃転⾞ 🚲 • ゲーム 🎮 • ⽝ 🐶 • 2024年9⽉に結婚しました💍 ⾃⼰紹介 2
Stream APIとTCPフロー制御 - Nihonbashi.js #9 はじめに • kintoneの拡張機能(プラグイン・連携サービス)向けの 開発基盤を開発・保守するチーム •
API開発 • SDK/CLIなどのOSS提供 など kintone拡張基盤🧩チーム 3
Streams API 4 WHATWGのStreams API (https://streams.spec.whatwg.org/)
Stream APIとTCPフロー制御 - Nihonbashi.js #9 Streams API • データ⼊出⼒を逐次的に、効率よく扱うためのAPI •
データを分割された断⽚(chunk)の連続した流れとして扱う • 概念⾃体はかなり古くからあり、多くの開発⾔語でストリーム操作はあります • 3種類のストリームオブジェクト(ReadableStream, WritableStream, TransformStream) • Stream同⼠をパイプ接続すると、chunkは流れるように終端まで処理される(パイプチェーン) Streams APIの概要 5 Transform Stream Readable Stream Writable Stream chunk データの読み込み データの変換 (読み込み+書き込み) データの書き込み chunk Source Sink
Stream APIとTCPフロー制御 - Nihonbashi.js #9 Streams API • ストリーム(オブジェクト)は未処理チャンクを保持する内部キューを持っている •
パイプチェーン上のストリーム間で処理速度に差がある場合、 内部キューにチャンクが溜まっていくことになる • => メモリを圧迫する︖ ストリームオブジェクト間の処理速度の違いとメモリ使⽤量 6 Transform Stream Readable Stream Writable Stream chunk chunk チャンクが溜まっていく︖ ここの処理が遅い場合 (DBアクセスなど)
Stream APIとTCPフロー制御 - Nihonbashi.js #9 Streams API • チャンクを受け⼊れられない場合、ストリームは上流に停⽌信号を出す •
停⽌信号を受けた上流のストリームはデータの送信を停⽌する • 下流のストリームが送信を指⽰(pull)すると再び処理が再開する => チャンクの流速が調整されてメモリを圧迫せずに処理できる 背圧 (Backpressure) 7 Transform Stream Readable Stream Writable Stream chunk chunk 内部キューが満杯 STOP! 内部キューが満杯 STOP!
Stream APIとTCPフロー制御 - Nihonbashi.js #9 Streams API • 背圧は内部キューの状態から、キューイング戦略に基づいて通知される •
現在は2種類のキューイング戦略が利⽤可能 キューイング戦略と最⾼⽔準点(highWaterMark) 8 キューに格納されたチャンク数で判定 キューに格納されたバイト数で判定 chunk chunk chunk chunk chunk chunk chunk chunk 3 最⾼⽔準点 (highWaterMark) 10KB CountQueuingStrategy ByteLengthQueuingStrategy
メモリリークと調査 9 ※このページ以降のデータ・グラフは再現リポジトリでの情報です。 (https://github.com/tasshi-playground/demo-stream-api-backpressure)
Stream APIとTCPフロー制御 - Nihonbashi.js #9 メモリリークと調査 • Webアプリケーションから全レコードを取得し、加⼯してDBに書き込んでいく • アプリケーションは全レコードをJSONL形式で返すAPIを持つ
• ストリームを使えばメモリに全レコードを載せずに効率よく処理できるはずだが、、、 全レコードへのバッチ処理 10 Text Decoder Stream Response JSON Parser Stream Line Splitter Stream ⾏ごとに 再分割 UTF-8 デコード DBに 書き込み レスポンスの 読み込み Writable Stream DBに 書き込み fetch DB
Stream APIとTCPフロー制御 - Nihonbashi.js #9 メモリリークと調査 • メモリを急速に圧迫した、なぜ︖ メモリリークの発⽣ 11
Stream APIとTCPフロー制御 - Nihonbashi.js #9 メモリリークと調査 • 終端ストリームを置き換え(DB => fs,
setTimeout)=> 効果なし • 中間ストリームを置き換え => 効果なし • 始端ストリームを置き換え(fetch => fs)=> 効果あり 原因箇所の特定 12 Response fetch Text Decoder Stream ここより前に原因がありそう
Stream APIとTCPフロー制御 - Nihonbashi.js #9 メモリリークと調査 • APIレスポンスはJSONL形式 (Content-Type: application/jsonl;
charset=utf-8) • HTTP/1.1 • Transfer-Encoding: chunked • ↑レスポンスはチャンク単位で送られてくる • => この通信に背圧が反映されないとResponse(ReadableStream)にチャンクが溜まるのでは︖ 通信の詳細 13 chunk Server chunk chunk Response STOP! STOP!…できてる︖
BackpressureとTCP通信 14 ※挙動ベースでの推察です (追ってNode.jsのコードを読んで裏付けしようと思います)
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • Server: JSONLを70MB返却するAPI •
Batch Runner: • APIを呼び出し、レスポンスをストリーム処理する • 終端のWritableStreamはチャンクを受け取ると⼀定時間待機する(背圧を発⽣させる) 検証環境 15 chunk Server (Express) Batch Runner chunk chunk HTTP WireShark キャプチャ
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • ウィンドウサイズはある程度⼤きい値を維持 • 受信側のチャンクサイズも⼩さい(受信速度より終端の処理速度が速い)
終端ストリームの遅延時間なしの場合 16 受信側のチャンクサイズ
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • ⼀定期間ごとにウィンドウサイズが急激に⼩さくなっていることが確認できた • チャンクサイズは上限値に張り付いていた
• => 背圧の発⽣がウィンドウサイズに反映されていると考えられる 終端ストリームの遅延時間100msの場合 17
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • Zero Windowが送信されていた •
ZeroWindow: ウィンドウサイズが0(通信⼀時停⽌) • ZeroWindowProveAck: 通信⼀時停⽌中の接続維持のためのACK • TCP Window Update: ウィンドウサイズが更新されて通信再開 • => よりキューの処理に時間がかかっていると考えられる 終端ストリームの遅延時間1000msの場合 18
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • Zero Window送信後、⻑時間に渡って通信再開せず •
=> 内部キューが処理できていないと考えられる 終端ストリームの遅延時間10000msの場合 19
Stream APIとTCPフロー制御 - Nihonbashi.js #9 BackpressureとTCP通信 • Streams APIの背圧はネットワークリクエストにも反映されると考えられる •
ウィンドウサイズが⼩さくなり、受信可能データ量を調整する • それでも処理しきれず受信を⽌める場合は、 サーバーにzero windowパケットが送信される • (HTTP/2での挙動も⾒てみたい) まとめ 20 chunk Server chunk chunk Response STOP! STOP! (zero window)
余談 21 メモリリークの原因はなんだったのか
Stream APIとTCPフロー制御 - Nihonbashi.js #9 22 メモリリークの原因
Stream APIとTCPフロー制御 - Nihonbashi.js #9 メモリリークの原因 • Node.js v22.7.0 (undici
v6.19.7)で修正された (nodejs/undici#3445) • v22ではメモリ使⽤量が300MB付近で横ばい • LTSへのbackport状況 • v20.x => v20.18.0にbackport済み、だが計測結果は× • v18.x => backportの予定は⾒つけられず undiciがメモリリークしていた 23
おわり 24 ご清聴ありがとうございました