aboutsummaryrefslogtreecommitdiffstats
path: root/client/go
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-04-24 13:34:48 +0200
committerMartin Polden <mpolden@mpolden.no>2023-04-24 13:48:26 +0200
commit1966902403aa9a5cec19eb9c51f7a3f0f1d0e80c (patch)
tree7b1cf10b09c2e72356eff909f197e0399fcc259e /client/go
parent81f2d7edf115a20b49ce3dd14ea174eabc253f4f (diff)
Re-use gzip writers
Diffstat (limited to 'client/go')
-rw-r--r--client/go/internal/vespa/document/http.go15
-rw-r--r--client/go/internal/vespa/document/http_test.go23
2 files changed, 36 insertions, 2 deletions
diff --git a/client/go/internal/vespa/document/http.go b/client/go/internal/vespa/document/http.go
index 0530144747a..877bcc5edce 100644
--- a/client/go/internal/vespa/document/http.go
+++ b/client/go/internal/vespa/document/http.go
@@ -11,6 +11,7 @@ import (
"net/url"
"strconv"
"strings"
+ "sync"
"sync/atomic"
"time"
@@ -31,6 +32,7 @@ type Client struct {
httpClients []countingHTTPClient
now func() time.Time
sendCount int32
+ gzippers sync.Pool
}
// ClientOptions specifices the configuration options of a feed client.
@@ -78,11 +80,13 @@ func NewClient(options ClientOptions, httpClients []util.HTTPClient) *Client {
if nowFunc == nil {
nowFunc = time.Now
}
- return &Client{
+ c := &Client{
options: options,
httpClients: countingClients,
now: nowFunc,
}
+ c.gzippers.New = func() any { return gzip.NewWriter(io.Discard) }
+ return c
}
func (c *Client) queryParams() url.Values {
@@ -167,18 +171,25 @@ func (c *Client) leastBusyClient() *countingHTTPClient {
return &leastBusy
}
+func (c *Client) gzipWriter(w io.Writer) *gzip.Writer {
+ gzipWriter := c.gzippers.Get().(*gzip.Writer)
+ gzipWriter.Reset(w)
+ return gzipWriter
+}
+
func (c *Client) createRequest(method, url string, body []byte) (*http.Request, error) {
var r io.Reader
useGzip := c.options.Compression == CompressionGzip || (c.options.Compression == CompressionAuto && len(body) > 512)
if useGzip {
var buf bytes.Buffer
- w := gzip.NewWriter(&buf)
+ w := c.gzipWriter(&buf)
if _, err := w.Write(body); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
+ c.gzippers.Put(w)
r = &buf
} else {
r = bytes.NewReader(body)
diff --git a/client/go/internal/vespa/document/http_test.go b/client/go/internal/vespa/document/http_test.go
index 314113c53be..f67368b5128 100644
--- a/client/go/internal/vespa/document/http_test.go
+++ b/client/go/internal/vespa/document/http_test.go
@@ -293,3 +293,26 @@ func TestClientFeedURL(t *testing.T) {
}
}
}
+
+func benchmarkClientSend(b *testing.B, compression Compression, document Document) {
+ httpClient := mock.HTTPClient{}
+ client := NewClient(ClientOptions{
+ Compression: compression,
+ BaseURL: "https://example.com:1337",
+ Timeout: time.Duration(5 * time.Second),
+ }, []util.HTTPClient{&httpClient})
+ b.ResetTimer() // ignore setup
+ for n := 0; n < b.N; n++ {
+ client.Send(document)
+ }
+}
+
+func BenchmarkClientSend(b *testing.B) {
+ doc := Document{Create: true, Id: mustParseId("id:ns:type::doc1"), Operation: OperationUpdate, Body: []byte(`{"fields":{"foo": "my document"}}`)}
+ benchmarkClientSend(b, CompressionNone, doc)
+}
+
+func BenchmarkClientSendCompressed(b *testing.B) {
+ doc := Document{Create: true, Id: mustParseId("id:ns:type::doc1"), Operation: OperationUpdate, Body: []byte(`{"fields":{"foo": "my document"}}`)}
+ benchmarkClientSend(b, CompressionGzip, doc)
+}