2013年8月22日木曜日

/etc/hosts はホスト数が増えるとDNSより遅くなる

/etc/hosts にホスト名を書いて配るというのは、数台のマシンを管理する状況では誰しもやったことがあると思います。DNSクエリが発生しないのでとても早く、また単一障害点が発生しないメリットがあります。その反面、台数が増えてくると全部を更新するのがとても大変になるだけでなく、致命的な速度低下をもたらします。

今回は /etc/hosts と dnsmasq でどの程度速度が変わるのかをベンチマークしました。

テスト環境は

  • OS: CentOS 6.4 64bit, Linux 3.10.2
  • CPU: Intel Core i7-2600 @ 3.4GHz
です。

テストにはひたすら getaddrinfo(3) し続けるプログラムを作成し、名前を解決しました。 /etc/hosts には

10.234.130.1 host1301
10.234.130.2 host1302
10.234.130.3 host1303

のように適当なアドレスとホスト名を並べたものを作り、利用しました。なお端数の2件はIPv4とv6のlocalhostです。

比較対象に dnsmasq をローカルに立てて同じ内容の hosts ファイルを読ませたものを使いました。

結果は次のとおりです。単位は秒で、10万クエリあたりの所要時間です。

#hostshostsdnsmasq
21.5164.8068
1022.65984.9224
2524.44744.9286
100213.23764.831


結果は一目瞭然で、ホストのエントリ数が増加するに従って、hosts を引く時間はほぼ線形に増加しています。今回の構成では損益分岐点はおよそ250エントリ程度となりました。なお hosts に見つからなかった場合は hosts の検索時間に加えて DNS を引く時間がかかります。

こうなる理由は、hosts の中身はライブラリ(libc)によって処理されていて、毎回 fopen(3) して線形に検索しているからです。dnsmasqをはじめとする多くのネームサーバーはファイルから読み込んだあと、ハッシュなどを使って高速に検索を行います。

実際には1リクエストあたりの時間に換算すると0.05マイクロ秒程度で、hostsに1000エントリ書いた場合でも0.14マイクロ秒なので大した時間ではありません。ですが、場合によってはhostsを引くよりきちんとDNSを使ったほうが早くなる場合があるということは覚えておいて損はありません。

測定に用いたプログラムは下記のとおりです。
2013/08/23 追記: タイトルが「急激に遅くなる」というのは煽っていると指摘を受けたので変更しました。 測定ポイント数が少ないのは単なる手抜きです...
「そんな多数のホストがある状態で /etc/hosts にすべて書くのはありえない」的な意見も見受けられましたが、実際にあるんですよ... そういう状態に対してきちんとエビデンスを示す目的で書かれました。 DNSで実際に速度や冗長性を担保するには別の工夫が必要になりますが、それはまた別の記事で。

あと nscd 使えばっていう話があったので参考までに1002エントリhostsで走らせたところ
$ ./a.out 100000 host127183
Resolved 100000 times. Elapsed time = 0.740 seconds, 0.007 us per host.

こんくらいの速度だったので、何も考えずに200倍早くなります。