skip-name-resolveでMySQLへの接続がどの程度速くなるのか試してみた

を見て、実際のところどの程度性能に影響があるのか気になったのでベンチを取ってみた。

ベンチマークスクリプトhttp://gist.github.com/594839で、connect -> disconnectを1000回繰り返すのにかかった時間を計測。

■計測結果

環境の詳細は後述するとして、まずは結果から。手動で何回か実行して、結果のボリュームゾーンを感覚的に抽出。

環境 実行時間(秒)
skip-name-resolve 1.73 〜 1.74
hosts 1.75 〜 1.76
DNS 2.26 〜 2.29

/etc/my.cnfでskip-name-resolveを有効にした場合、確かに速くて、DNSで名前解決するよりも0.5秒ぐらい速くなる。1回あたり0.5msecをどう見るかはケースバイケースだが、DB接続だけでこれだけ変わるのであれば採用したいなと思った。

ただ、hostsで名前解決が出来る場合はほとんど誤差程度の違いしか見られなかった。繰り返しテストすると確かにskip-name-resolve使用時の方が速い傾向が出るが、必ず毎回そうなるわけではなく、hostsの方が速いこともあった。

MySQL公式の「6.5.6. MySQLの DNS の使用」によれば、

オペレーティングシステムがスレッドセーフの gethostbyaddr_r()とgethostbyname_r()の呼び出しをサポートしている場合、スレッドではこれを使用してホスト名の解決が実行される。

とあるが、この呼び出しを省略することによるパフォーマンス向上はそれほど大きくはない印象です。

どちらかと言えば、hostsとDNSでこれぐらい差が付くんだなーということの方が印象的なテストになった。DNSはdnscache(djbdns)を使っているが、これがbindだったりunboundだった場合にどうなるかは調べていない。

内部で多数の通信が必要なアプリケーションでは、多少面倒でもhostsで名前解決するような運用にした方が有利なのかな。あと、クライアントでのDBサーバの名前解決はhostsに書いてるんだけど、これをDNS参照すると0.3秒ぐらい遅くなった。

skip-name-resolveを有効にすると、「localhost」も名前として使えなくなるらしいので注意が必要。MySQLlocalhostはソケットで、127.0.0.1TCPで接続しているようなので、そこを厳密にしたい場合は使えないと思われます(以前、mysqld_multiで接続をうまく使い分けてくれなくて、localhost127.0.0.1が同じ物だという前提に基づいたアプリが問題だったことがある)。このへんはあまり興味ないので全く調べてない。

■実施環境

client
OS CentOS5.4
CPU Athlon64 3500+ (1core 2.2GHz)
memory DDR2 1GB
memo Xen上の仮想マシン
DB server
OS CentOS5.5
CPU Xeon X3330 (4core 2.66GHz) (C2Q相当)
memory DDR2 8GB
MySQL 5.1.49 + InnoDB plugin
memo clientとは別の物理サーバ
DNS
  • clientマシンで稼働
  • dnscache(djbdns)を使用
network
  • 100Mの古い安物ハブ
  • GbEなら改善されるかも

■まとめ

  • DNSで名前解決するならskip-name-resolveは検討の価値あり
  • hostsだと誤差程度の差なので、skip-name-resolveその物はそんなに速さに貢献しない
  • hostsとDNSの差が思った以上にあるので、積極的にhostsに書いていきたい
  • 個人的にはhostsをPuppetで配布するアプローチで必要十分な感がある

(追記)ベンチマークスクリプトをDBサーバで実行したら、0.41〜0.48秒ぐらいでした。名前解決はhostsでプライベートIPを指定。ネットワークの差か、CPUの差か。多分CPUの差だと思うけど、機材が足りなくて検証出来ません。

(追記2)DBサーバからプライベートIPをDNSで名前解決させたら0.74〜0.78秒ぐらい。hostsの方が速いけど、最初のテスト環境よりも差は小さい。DNSサーバを高スペックな物にすれば更に差は縮まるような気がしてきました。まぁでも、この差が気になる環境だと内部のトラフィックを減らすためにhosts書くメリットが大きいんじゃないかな。