LoginSignup
29
12

More than 5 years have passed since last update.

Dockerコンテナとネイティブ実行の速度比較

Last updated at Posted at 2017-11-19

はじめに

DockerはLinux上でのコンテナ型仮想化技術の一つである。ホストOSと同じLinuxカーネルしか動かすことできないという制約はあるが、従来のハイバーバイザー型の仮想化技術に比べて起動が速く性能的なペナルティが少ないと言われる。とは言え、何らかのオーバーヘッドがあるはずで、それをちょっと調べてみた。

テスト環境

本来であればLinuxマシンの上でホストとDocker上の比較をすべきと思うが、手元には古めのMac(MacBookAir4,2 13-inch Mid 2011)しかなく、それで確認をしてみた。DockerのランタイムはVersion 17.09.0-ce-mac35 (19611)。
ちなみに、MacOSの上でなぜDockerが動くのか?DockerはLinuxカーネルの上でしか動かないんじゃないのか? それはそうなんだけど、最近のMacOSにはHypervisor Frameworkというのが載っていてそこで別のOSを動かせる。Dockerはこの上にHyperkitというツールキットを載せ、その上でLinuxカーネルを動かしている。DockerのコンテナはそのLinux上で動くという構成だ。ここの記事に図入りで簡潔に説明されています。

比較実験

比較に使ったのはredisというキー・バリュー型のデータベース。これにredis-benchmarkという性能評価のツールが付属しているのでこれを使ってみる。
測ったのは次の3パターン。どれもバージョンは4.0.2。

  1. Native: MacOSの上で直接動かす (brew install redisでインストール)
  2. Docker: 一つのDockerコンテナ上で動かす
  3. Docker.Remote: redisとredis-benchmarkを別のDockerコンテナで動かす

そして1と2に関しては、tcpのport(デフォルトで6379)に接続する方法と、Unix domain socketで接続する方法(すなわちプロセス間通信)の2種類ができるのでそれを試している。便宜上、前者をtcp接続、後者をunix接続と呼ぶことにする

実験結果

一覧の表にしてみた。

Native(tcp) Native(unix) Docker(tcp) Docker(unix) Docker.remote
PING_INLINE 24384.3 77942.32 48899.75 81900.09 36469.73
PING_BULK 26068.82 88105.73 48638.13 85910.65 37133.31
SET 26567.48 88261.25 52002.08 90415.91 37792.89
GET 27300.03 83612.04 48100.05 82576.38 37411.15
INCR 27685.49 79554.5 51519.84 88028.16 38431.98
LPUSH 27329.87 86132.64 52029.14 97181.73 36968.58
RPUSH 20404.0 86355.79 54112.55 88652.48 39385.59
LPOP 22456.77 85034.02 52603.89 93632.96 39968.02
RPOP 24746.35 79681.27 52994.17 85543.2 36818.85
SADD 24324.98 94428.7 49504.95 91491.3 33156.5
HSET 23866.35 93545.37 53648.07 95057.03 36778.23
SPOP 24734.11 90497.73 47801.15 91996.32 32541.49
LPUSH(neededtobenchmarkLRANGE) 24336.82 94786.73 53734.55 90826.52 38417.21
LRANGE_100(first100elements) 9061.25 15581.18 28785.26 38328.86 22655.19
LRANGE_300(first300elements) 4830.68 6147.42 12247.4 14836.8 8915.04
LRANGE_500(first450elements) 3478.38 4192.34 9373.83 10488.78 7043.74
LRANGE_600(first600elements) 2917.66 3113.81 7452.68 7990.41 5470.76
MSET(10keys) 21294.72 51679.59 55928.41 98328.42 36036.04

でもこれだとちょっとわかりにくいので、pandasmatplotlibを使ってグラフにしてみた。

tcp接続とunix接続の比較

MacOS NativeでもDockerの上でもUnix接続のほうが断然早い。まあこれはTCPのオーバーヘッドを考えれば当然の結果。
fig0.png
fig3.png

MacOS NativeとDockerの比較

これが本題の比較なのだが、ちょっと意外な結果。

fig1.png
fig2.png

Unix Socket接続の方はドッコイドッコイだが(これも少し差が付くと思っていたので意外は意外)、TCP接続の方はなぜかDockerの方が早い。何回かやってみるとやる度にそれなりに値が振れるのだが、傾向としてDockerの方が早そうというのは変わらない。コレなんでだろうな...

Dockerのコンテナを別にした時との比較

通常Dockerでは「1サービス1コンテナ」というポリシーで運用するのでそれに従うとRedisを稼働させるコンテナとそれを使うロジックを実装するコンテナは別になる。その構成だとTCP接続しか出来ないのだが、それを1コンテナ構成で一緒にした時との比較をしてみるとこんな感じ。
fig4.png

この差が大きいか小さいかは用途次第だけど、確かに差はあることがわかる。

まとめ

予想外の結果が出ていてちょっと戸惑っているが、一つ目の結論は

  • Linuxマシンの上で比較してみたい。

ということ。

そして、例えばRedisを一つのクライアントからだけ使うなら

  • 同じコンテナに入れてUnix domainのソケット接続をする

のも性能を稼ぎたい場合はありなのかな。

そして今回の実験につかったソース他はこちら

29
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
12