brendanw / profilehttp

Compare okhttp and ktor http client performance

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Initial Results

Tests okhttp ktor numThreads=8 ktor numThreads=1
client init
init client + 10 status code requests 676 ms 285ms 243ms
pre-initialized client + 10 status code requests 8ms 8ms 19ms
read 1 medium-sized responses from same endpoint
read 10 medium-sized responses from same endpoint 14ms 50ms 3057ms
read 100 medium-sized responses from same endpoint 78ms 153ms 2186ms
read 1,000 medium-sized responses from same endpoint 284ms 553ms 1587ms
read 10,000 medium-sized responses from same endpoint 1967ms crash 8815ms
read 100,000 medium-sized responses from same endpoint

Run the tests

You'll need gradle to build both the client and server projects:

on mac: brew install gradle (see https://brew.sh/ to install homebrew)

on windows: choco install gradle (see https://chocolatey.org/ to install chocolatey)

Before running the client tests, be sure to start up the server

cd server && ./gradlew run

You can run the ktor cio client performance test from within the client directory with

cd client && ./gradlew -PmainClass=KtorKt run

Run the okhttp client performance test with

cd client && ./gradlew -PmainClass=OkhttpKt run

Alternatively you can just run the shell script

sh runtest.sh

For opening the project and running tests within intellij, be sure that there are only two modules client and server. If you need to add either module, you can do so via "open module settings" => "+" => "new module" and then enter the location of the client or server folder.

Background

The goal is to reduce thread usage in the typical android app. A typical android app has 50-100 threads allocated at a given time. If yes, can we see performance improvements?

Asked on the Kotlin Lang slack (https://kotlinlang.slack.com/archives/C0B8M7BUY/p1575401896314500):

Dispatchers.IO defaults to being backed by an executor that can spawn up to 64 threads. Is it possible to architect an app with suspending non-blocking IO calls and we'd just use one thread for the IO dispatcher?

Is it a reasonable expectation that migrating to coroutines+flow from rx will reduce the total number of threads an android application uses? This is the high-level question I am trying to answer.

Stumbled upon this comment by Roman Elizarov

If you are using a library that provides asynchronous IO via NIO (like ktor.io for example), then you would not need withContext at all, since all your IO functions will be non-blocking. You need to use Dispatchers.IO only if you have blocking IO functions that you must to use without blocking.

Jesse Wilson suggested performance testing the two clients.

To see where okhttp does blocking network io for http1.1 requests visit https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/http1/Http1ExchangeCodec.kt

To see where ktor-client manages nio for http1.1 requests visit https://github.com/ktorio/ktor/blob/master/ktor-network/jvm/src/io/ktor/network/selector/ActorSelectorManager.kt

A primer on nio https://www.hellsoft.se/non-blocking-io/

Hypothesis 1

Using the ktor client configured to a single thread should have similar performance to using okhttp launching a thread for each request.

Hypothesis 2

The ktor client performance should improve as we increase the number of threads it is configured to use.

Hypothesis 3

The number of running threads -- ceteris paribus -- should be lower in an application using the ktor client.

Flaws

-The mechanism for determining when 10 concurrent requests are complete is different in each experiment. The performance of CountDownLatch vs List:awaitAll() could have a significant impact. We should try to find a way to use the same mechanism for each test set.

-Running into an error at 100_000 concurrent requests for ktor. Need to dig into to see if we are using the library wrong or its a bug.

-Measurements are not guaranteed to include garbage collection

-Should test for when each request is for a different address

-Should compare 1 request vs 1 request

-Should stagger when execution starts for each request to mimic analytics calls

About

Compare okhttp and ktor http client performance


Languages

Language:Kotlin 97.7%Language:Shell 2.3%