go-httpstatでリクエストにかかった時間の割合をみる

golangでhttpリクエストするときにkeepaliveにしたらどれくらいリクエストにかかる時間減るのかを知りたかったのだが、こういうライブラリがあるのを知った。

https://github.com/tcnksm/go-httpstat

実際は net/http/httptrace をラップしているだけっぽい。ただこれくらいのコードで情報が出てきて便利。

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/tcnksm/go-httpstat"
)

func main() {
	args := os.Args
	if len(args) < 2 {
		log.Fatalf("Usage: go run main.go URL")
	}
	req, err := http.NewRequest("GET", args[1], nil)
	if err != nil {
		log.Fatal(err)
	}

	var result httpstat.Result
	ctx := httpstat.WithHTTPStat(req.Context(), &result)
	req = req.WithContext(ctx)

	client := http.DefaultClient
	res, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}

	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
		log.Fatal(err)
	}
	res.Body.Close()
	result.End(time.Now())

	fmt.Printf("%+v\n", result)
}
DNS lookup:           0 ms
TCP connection:     178 ms
TLS handshake:      266 ms
Server processing:  409 ms
Content transfer:     0 ms

Name Lookup:       0 ms
Connect:         179 ms
Pre Transfer:    446 ms
Start Transfer:  409 ms
Total:           409 ms

当然と言われれば当然なんだけど、TCPの3way handshakeだけでも結構時間かかるんだなというのがわかった。サーバーのコンテンツ生成がほぼ全ての時間かかってるイメージだったが、こうやって自分で計測してみると全然そんなことないんだなというのがわかる。そりゃkeepaliveみたいなの使ってコネクション使いまわしたくなるわけだ。

あとローカルでサーバーたててもDNSルックアップにかかる時間はほとんどない。そういう時に手軽にローカルじゃない環境作るのにngrok使えばええという知見も得られた。

参考: https://christina04.hatenablog.com/entry/go-keep-alive