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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
tasshi
October 31, 2024
Programming
680
2
Share
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
More Decks by tasshi
See All by tasshi
開発者から情シスまで - 多様なユーザー層に届けるAPI提供戦略 / Postman API Night Okinawa 2026 Winter
tasshi
0
250
プロダクトにも、チームにも。サイボウズがAIと共に歩む理由 / YAPC 2025 Cybozu Team AI
tasshi
0
510
Web Streams APIの基本と実践、TypeScriptでの活用法 / TSKaigi 2025 Web Streams API
tasshi
6
2.1k
2024年のkintone API振り返りと2025年 / kintone API look back in 2024
tasshi
0
380
GitHub Projectsを自動化するGitHub CLIテクニック / Automate GitHub Projects with GitHub CLI
tasshi
2
2k
SDK開発チームのプロダクトオーナーが考えていること / Product management of SDK
tasshi
1
2k
Node.js製CLIツールのE2Eテストに取り組んでいます / Working on E2E testing of Node.js CLI tools
tasshi
0
1.7k
モダンな開発環境を用いた カンタン/安全なカスタマイズ開発 / kintone devCamp Boost! 2023
tasshi
0
1k
Node Streamでメモリ性能改善、そしてWeb Streams APIへ / Improving memory performance of the CLI tool using Node Stream
tasshi
1
3.8k
Other Decks in Programming
See All in Programming
Redox OS でのネームスペース管理と chroot の実現
isanethen
0
500
PHP 7.4でもOpenTelemetryゼロコード計装がしたい! / PHPerKaigi 2026
arthur1
1
460
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
1.3k
GC言語のWasm化とComponent Modelサポートの実践と課題 - Scalaの場合
tanishiking
0
140
The free-lunch guide to idea circularity
hollycummins
0
400
Migration to Signals, Signal Forms, Resource API, and NgRx Signal Store @Angular Days 03/2026 Munich
manfredsteyer
PRO
0
210
安いハードウェアでVulkan
fadis
1
870
Laravel Nightwatchの裏側 - Laravel公式Observabilityツールを支える設計と実装
avosalmon
1
300
Coding at the Speed of Thought: The New Era of Symfony Docker
dunglas
0
4.1k
野球解説AI Agentを開発してみた - 2026/02/27 LayerX社内LT会資料
shinyorke
PRO
0
380
2026-03-27 #terminalnight 変数展開とコマンド展開でターミナル作業をスマートにする方法
masasuzu
0
270
Java 21/25 Virtual Threads 소개
debop
0
320
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
170
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
110
KATA
mclloyd
PRO
35
15k
Automating Front-end Workflow
addyosmani
1370
200k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
170
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
150
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
500
Scaling GitHub
holman
464
140k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
120
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.2k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
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 ご清聴ありがとうございました