Skip to content

Commit

Permalink
Improves performance of json responses (grafana#7522)
Browse files Browse the repository at this point in the history
**What this PR does / why we need it**:

This allows to reuse stream memory allocations between responses.
Related grafana#3163 but this time this is
for the encoding.

```
❯ benchstat before.txt after.txt                                                                                                              
name        old time/op    new time/op    delta
_Encode-16    29.2µs ±12%    25.2µs ± 1%  -13.85%  (p=0.016 n=5+4)

name        old alloc/op   new alloc/op   delta
_Encode-16    24.9kB ± 6%    16.4kB ± 8%  -34.20%  (p=0.008 n=5+5)

name        old allocs/op  new allocs/op  delta
_Encode-16       145 ± 0%       129 ± 0%  -11.03%  (p=0.008 n=5+5)
```
  • Loading branch information
cyriltovena authored and lxwzy committed Nov 7, 2022
1 parent 7b3a178 commit cd6a5d4
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions pkg/util/marshal/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ func WriteQueryResponseJSON(v logqlmodel.Result, w io.Writer) error {
},
}

return jsoniter.NewEncoder(w).Encode(q)
s := jsoniter.ConfigFastest.BorrowStream(w)
defer jsoniter.ConfigFastest.ReturnStream(s)
s.WriteVal(q)
s.WriteRaw("\n")
return s.Flush()
}

// WriteLabelResponseJSON marshals a logproto.LabelResponse to v1 loghttp JSON
Expand All @@ -43,7 +47,11 @@ func WriteLabelResponseJSON(l logproto.LabelResponse, w io.Writer) error {
Data: l.GetValues(),
}

return jsoniter.NewEncoder(w).Encode(v1Response)
s := jsoniter.ConfigFastest.BorrowStream(w)
defer jsoniter.ConfigFastest.ReturnStream(s)
s.WriteVal(v1Response)
s.WriteRaw("\n")
return s.Flush()
}

// WebsocketWriter knows how to write message to a websocket connection.
Expand Down Expand Up @@ -77,7 +85,11 @@ func WriteSeriesResponseJSON(r logproto.SeriesResponse, w io.Writer) error {
adapter.Data = append(adapter.Data, series.GetLabels())
}

return jsoniter.NewEncoder(w).Encode(adapter)
s := jsoniter.ConfigFastest.BorrowStream(w)
defer jsoniter.ConfigFastest.ReturnStream(s)
s.WriteVal(adapter)
s.WriteRaw("\n")
return s.Flush()
}

// This struct exists primarily because we can't specify a repeated map in proto v3.
Expand All @@ -90,5 +102,9 @@ type seriesResponseAdapter struct {
// WriteIndexStatsResponseJSON marshals a gatewaypb.Stats to JSON and then
// writes it to the provided io.Writer.
func WriteIndexStatsResponseJSON(r *stats.Stats, w io.Writer) error {
return jsoniter.NewEncoder(w).Encode(r)
s := jsoniter.ConfigFastest.BorrowStream(w)
defer jsoniter.ConfigFastest.ReturnStream(s)
s.WriteVal(r)
s.WriteRaw("\n")
return s.Flush()
}

0 comments on commit cd6a5d4

Please sign in to comment.