diff --git a/api/client.go b/api/client.go index f7ca60b67..1413f65fe 100644 --- a/api/client.go +++ b/api/client.go @@ -15,8 +15,8 @@ package api import ( + "bytes" "context" - "io/ioutil" "net" "net/http" "net/url" @@ -111,7 +111,9 @@ func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, var body []byte done := make(chan struct{}) go func() { - body, err = ioutil.ReadAll(resp.Body) + var buf bytes.Buffer + _, err = buf.ReadFrom(resp.Body) + body = buf.Bytes() close(done) }() diff --git a/api/client_test.go b/api/client_test.go index 47094fccd..4215c73db 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -14,7 +14,11 @@ package api import ( + "bytes" + "context" + "fmt" "net/http" + "net/http/httptest" "net/url" "testing" ) @@ -111,3 +115,50 @@ func TestClientURL(t *testing.T) { } } } + +// Serve any http request with a response of N KB of spaces. +type serveSpaces struct { + sizeKB int +} + +func (t serveSpaces) ServeHTTP(w http.ResponseWriter, req *http.Request) { + kb := bytes.Repeat([]byte{' '}, 1024) + for i := 0; i < t.sizeKB; i++ { + w.Write(kb) + } +} + +func BenchmarkClient(b *testing.B) { + b.ReportAllocs() + ctx := context.Background() + + for _, sizeKB := range []int{4, 50, 1000, 2000} { + b.Run(fmt.Sprintf("%dKB", sizeKB), func(b *testing.B) { + + testServer := httptest.NewServer(serveSpaces{sizeKB}) + defer testServer.Close() + + client, err := NewClient(Config{ + Address: testServer.URL, + }) + if err != nil { + b.Fatalf("Failed to initialize client: %v", err) + } + url, err := url.Parse(testServer.URL + "/prometheus/api/v1/query?query=up") + if err != nil { + b.Fatalf("Failed to parse url: %v", err) + } + req := &http.Request{ + URL: url, + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _, err := client.Do(ctx, req) + if err != nil { + b.Fatalf("Query failed: %v", err) + } + } + b.StopTimer() + }) + } +}