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
Request in a QUIC way @shibuya.apk#28
Search
TakuSemba
September 27, 2018
Technology
1.1k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Request in a QUIC way @shibuya.apk#28
TakuSemba
September 27, 2018
More Decks by TakuSemba
See All by TakuSemba
Customize & Debug ExoPlayer @droidkaigi 2020
takusemba
0
2.1k
Jetpack Compose
takusemba
3
3.7k
Protobuf in Kotlin
takusemba
2
2k
Single Activity with MVVM
takusemba
4
1.4k
KotlinConf Report @ca.kt#7
takusemba
2
500
Lint for Kotlin @R.kt#3
takusemba
3
1.6k
Auto Release @potatochips#48
takusemba
1
1.3k
Media streaming on Android @droidkaigi 2018
takusemba
6
8.3k
gRPC on Android @DroidconSF Report
takusemba
1
640
Other Decks in Technology
See All in Technology
SRE依存からの脱却 運用を開 発チームへ移す、 フルサイ クル開 発体制の実践
joooee0000
0
2.8k
なぜ私たちのSREプラクティスはなかなか機能しないのか 〜システムより先に組織を見る〜 / Why our SRE practices aren't really working
vtryo
3
3.8k
Claude Code公式skillで 自分の仕事を少しずつ手放そう!(Claude Code開発ノウハウ大公開スペシャル by クラスメソッド)
kaym
1
380
シンガポールで登壇してきます
yama3133
0
200
「ちゃんとやっている」は独りよがりだった ― 不安に寄り添うインシデント対応へ / Towards incident response that addresses anxieties
chmikata
1
5.5k
人を動かすのは時間ではなく、納得感 〜新任EMが入社3ヶ月、組織を2回変えた話〜
kakehashi
PRO
3
250
AIレビューはどこまで任せられるのか?自動化と人が背負うレビューの境界
sansantech
PRO
3
900
誤解だらけの開発生産性 / Myths and Misconceptions about Developer Productivity
i35_267
2
660
アカウントが増えてからでは遅い? ~ マルチアカウント統制の勘所 ~
kenichinakamura
0
240
事業価値を⽣み出すSREへ SREが担うべき意思決定の5層
kenta_hi
2
3.7k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
15
110k
【Claude Code】鹿野さんに聞く 私の推しの並行開発環境 大公開 / claude-code-parallel-2026-07-15
tonkotsuboy_com
11
8k
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Color Theory Basics | Prateek | Gurzu
gurzu
0
390
Docker and Python
trallard
47
4k
[SF Ruby Conf 2025] Rails X
palkan
2
1.2k
A better future with KSS
kneath
240
18k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
190
Embracing the Ebb and Flow
colly
88
5.1k
Optimizing for Happiness
mojombo
378
71k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
190
The SEO Collaboration Effect
kristinabergwall1
1
500
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
410
Transcript
None
@takusemba https://github.com/TakuSemba
QUIC?
Quick UDP Internet Connections
QUIC
Google QUIC https://www.chromium.org/quic
QUIC for IETF https://tools.ietf.org/html/draft-hamilton-early-deployment-quic-00
Merits
Merits ɾConnection establishment latency
Connection establishment latency Client Server
Connection establishment latency TCP Client Server
Connection establishment latency TCP Client Server
Connection establishment latency Client Server TCP + TLS
Connection establishment latency TCP + TLS Client Server
Connection establishment latency TCP + TLS Client Server 1-3 roundtrips
Connection establishment latency TCP + TLS Application Data Client Server
1-3 roundtrips
Connection establishment latency QUIC Client Server
Connection establishment latency QUIC Client Server
Connection establishment latency QUIC Client Server 0-1 roundtrips
Connection establishment latency QUIC Application Data Client Server 0-1 roundtrips
Merits ɾConnection establishment latency
Merits ɾConnection establishment latency ɾMultiplexing
Multiplexing TCP Client Server
Multiplexing TCP Client Server
Multiplexing TCP head of line blocking Client Server
Multiplexing QUIC stream 1 stream 2 stream 3 Client Server
Multiplexing QUIC stream 1 stream 2 stream 3 Client Server
Multiplexing QUIC … … stream 1 stream 2 stream 3
Client Server
Merits ɾConnection establishment latency ɾMultiplexing
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration
Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: xxx.xxx.xxx.xxx Port:
aa Client Server
Connection Migration TCP IP: yyy.yyy.yyy.yyy Port: bb IP: zzz.zzz.zzz.zzz Port:
cc Client Server
Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client
Server
Connection Migration QUIC Connection ID: xxxxxx Connection ID: yyyyyy Client
Server
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control
Merits ɾConnection establishment latency ɾMultiplexing ɾConnection Migration ɾCongestion Control ɾForward
Error Correction
Cronet
https://developer.android.com/guide/topics/connectivity/cronet
Quicstart
dependencies { implementation "org.chromium.net:cronet-embedded:x.x.x" }
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .enableQuic(true)
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() newUrlRequestBuilder(url, callback, executor)
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() .setHttpMethod("GET") .addHeader("hoge", "huga")
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start()
val cronetEngine = CronetEngine.Builder(context) .enableHttp2(true) .enableQuic(true) .build() val request =
cronetEngine.newUrlRequestBuilder(url, callback, executor) .setHttpMethod("GET") .addHeader("hoge", "huga") .build() request.start() callback
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) } … } override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { // read response request.read(ByteBuffer.allocateDirect(32 * 1024)) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( byteBuffer: ByteBuffer
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) } … } override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, byteBuffer: ByteBuffer) { // write response byteBuffer.flip() receiveChannel.write(byteBuffer) // read response byteBuffer.clear() request.read(byteBuffer) }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() } … } override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { // succeeded val result = bytesReceived.toByteArray() }
val callback = object : UrlRequest.Callback() { private val bytesReceived
= ByteArrayOutputStream() private val receiveChannel = Channels.newChannel(bytesReceived) override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") } … } override fun onFailed(request: UrlRequest, info: UrlResponseInfo, e: CronetException) { // failed Log.d("CRONET_SAMPLE", "failed: ${e.message}") }
QUIC for ExoPlayer
https://github.com/google/ExoPlayer/tree/release-v2/extensions/cronet
Client .m3u8 .mp4 .mp4 .ts OkHttp
Client .m3u8 .mp4 .mp4 .ts Cronet
OkHttpClient
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } Cronet
val userAgent = "takusemba" val okHttpClient = OkHttpClient() val transferListener
= DefaultBandwidthMeter() val factory = OkHttpDataSourceFactory(okHttpClient, userAgent, transferListener) OkHttpClient Cronet val userAgent = "takusemba" val cronetEngine = CronetEngine.Builder(context).enableQuic(true).build() val wrapper = CronetEngineWrapper(cronetEngine) val executor = Executors.newSingleThreadExecutor() val predicate = Predicate { contentType: String -> true } val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent) val factory = CronetDataSourceFactory(wrapper, executor, predicate, userAgent)
None
https://github.com/TakuSemba/QuicPlayer Sample App
https://github.com/takusemba https://twitter.com/takusemba Request in a QUIC way