curlで150ms損していた話


## curlと127.0.0.1とlocalhost

curlでレスポンスタイムを取得して、その値を監視していたのだけど
ホストの指定を「127.0.0.1」にするか「localhost」にするかで結果がだいぶ違う。
どのくらい違うかというとこのくらい。

```
$ curl -skL -o /dev/null -w "%{time_total}\n" http://127.0.0.1/test.html
0.001
$ curl -skL -o /dev/null -w "%{time_total}\n" http://localhost/test.html
0.152
```

ちなみにDigitalOceanのCentOS 7です。

```
$ uname -a
Linux web01 3.10.0-123.8.1.el7.x86_64 #1 SMP Mon Sep 22 19:06:58 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.15.4 zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz
$
```


## どこが遅いか

こちらのサイトを参考にさせてもらって、どこが遅いのか調べてみます。
curlでボトルネック調査をする
http://d.hatena.ne.jp/akuwano/20120503/1335994486


### curl 7.29.0で、127.0.0.1の場合

```
$ curl -o /dev/null 'http://127.0.0.1/test.html' -w @/tmp/curl_env.txt -s
url_effective           : http://127.0.0.1/test.html
http_code               : 200
http_connect            : 000
time_total              : 0.001
time_namelookup         : 0.000
time_connect            : 0.000
time_appconnect         : 0.000
time_pretransfer                : 0.000
time_redirect           : 0.000
time_starttransfer              : 0.001
size_download           : 48894
size_upload             : 0
size_header             : 240
size_request            : 82
speed_download          : 44815765.000
speed_upload            : 0.000
$
```

### curl 7.29.0で、localhostの場合

```
$ curl -o /dev/null 'http://localhost/test.html' -w @/tmp/curl_env.txt -s
url_effective           : http://localhost/test.html
http_code               : 200
http_connect            : 000
time_total              : 0.152
time_namelookup         : 0.151
time_connect            : 0.151
time_appconnect         : 0.000
time_pretransfer                : 0.151
time_redirect           : 0.000
time_starttransfer              : 0.152
size_download           : 48894
size_upload             : 0
size_header             : 240
size_request            : 82
speed_download          : 322339.000
speed_upload            : 0.000
$
```

localhostの場合150msくらい遅いです。もう答えっぽいのが見えてますけど、気にしない。

## straceしてみる

遅いケースを、straceで追いかけてみます。

```
strace -tt -s 1024 curl -skL http://localhost/test.html > /dev/null
```

とかすると、

```
poll(0, 0, 150)                         = 0 (Timeout)
```
なんか怪しいのがでてます。150だし。
で、このままググるとすぐに答えが出てきちゃうんだけど、ここにたどり着きました。

Bug 1130239 - Difference in curl performance between RHEL6 and RHEL7
https://bugzilla.redhat.com/show_bug.cgi?id=1130239

要するにlibcurlのバグってことですかね。

## 新しいcurlでやってみる

http://curl.haxx.se/download.html
から新しそうなやつをダウンロードしてコンパイルします。
オプションを間違えたのでインストールパスがビンビンですが気にしない。

```
$ /usr/local/bin/bin/curl -V
curl 7.46.0 (x86_64-pc-linux-gnu) libcurl/7.46.0
Protocols: dict file ftp gopher http imap pop3 rtsp smtp telnet tftp
Features: IPv6 Largefile UnixSockets
$
```

### curl 7.46.0で、127.0.0.1の場合

```
$ /usr/local/bin/bin/curl -o /dev/null 'http://127.0.0.1/test.html' -w @/tmp/curl_env.txt -s
url_effective           : http://127.0.0.1/test.html
http_code               : 200
http_connect            : 000
time_total              : 0.001
time_namelookup         : 0.000
time_connect            : 0.000
time_appconnect         : 0.000
time_pretransfer                : 0.001
time_redirect           : 0.000
time_starttransfer              : 0.001
size_download           : 48894
size_upload             : 0
size_header             : 240
size_request            : 82
speed_download          : 40677204.000
speed_upload            : 0.000
$
```

### curl 7.46.0で、localhostの場合

```
$ /usr/local/bin/bin/curl -o /dev/null 'http://localhost/test.html' -w @/tmp/curl_env.txt -s
url_effective           : http://localhost/test.html
http_code               : 200
http_connect            : 000
time_total              : 0.001
time_namelookup         : 0.001
time_connect            : 0.001
time_appconnect         : 0.000
time_pretransfer                : 0.001
time_redirect           : 0.000
time_starttransfer              : 0.001
size_download           : 48894
size_upload             : 0
size_header             : 240
size_request            : 82
speed_download          : 34505292.000
speed_upload            : 0.000
$
```

同じくらいになったのでよしとする。


## おまけ

こういう時、127.0.0.1 と 127.1 と 0 は等価かと思ったけど、結果はこうなった。ややこしい。

```
(curl 7.29.0)
$ curl -skL -o /dev/null -w "%{time_total}\n" http://127.0.0.1/test.html
0.001
$ curl -skL -o /dev/null -w "%{time_total}\n" http://127.1/test.html
0.151
$ curl -skL -o /dev/null -w "%{time_total}\n" http://0/test.html
0.152
$
```

ヘイ！カール！
https://www.youtube.com/watch?v=yJl7VV4rrT0