Skip to content

Commit c998149

Browse files
coocooddfawley
authored andcommitted
Avoid copying headers/trailers in unary RPCs unless requested by CallOptions (grpc#1775)
CPU profile shows that header copy takes a large proportion of CPU usage in a gRPC Call. If the header is not needed, we don't need to pay the cost.
1 parent 8246210 commit c998149

File tree

3 files changed

+14
-22
lines changed

3 files changed

+14
-22
lines changed

call.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"google.golang.org/grpc/balancer"
2828
"google.golang.org/grpc/codes"
2929
"google.golang.org/grpc/encoding"
30-
"google.golang.org/grpc/peer"
3130
"google.golang.org/grpc/stats"
3231
"google.golang.org/grpc/status"
3332
"google.golang.org/grpc/transport"
@@ -47,10 +46,6 @@ func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTran
4746
}
4847
}
4948
}()
50-
c.headerMD, err = stream.Header()
51-
if err != nil {
52-
return
53-
}
5449
p := &parser{r: stream}
5550
var inPayload *stats.InPayload
5651
if dopts.copts.StatsHandler != nil {
@@ -84,7 +79,6 @@ func recvResponse(ctx context.Context, dopts dialOptions, t transport.ClientTran
8479
// Fix the order if necessary.
8580
dopts.copts.StatsHandler.HandleRPC(ctx, inPayload)
8681
}
87-
c.trailerMD = stream.Trailer()
8882
return nil
8983
}
9084

@@ -269,9 +263,7 @@ func invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
269263
}
270264
return toRPCErr(err)
271265
}
272-
if peer, ok := peer.FromContext(stream.Context()); ok {
273-
c.peer = peer
274-
}
266+
c.stream = stream
275267
if c.traceInfo.tr != nil {
276268
c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)
277269
}

rpc_util.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,7 @@ func (d *gzipDecompressor) Type() string {
125125
type callInfo struct {
126126
compressorType string
127127
failFast bool
128-
headerMD metadata.MD
129-
trailerMD metadata.MD
130-
peer *peer.Peer
128+
stream *transport.Stream
131129
traceInfo traceInfo // in trace.go
132130
maxReceiveMessageSize *int
133131
maxSendMessageSize *int
@@ -172,24 +170,30 @@ func (o afterCall) after(c *callInfo) { o(c) }
172170
// for a unary RPC.
173171
func Header(md *metadata.MD) CallOption {
174172
return afterCall(func(c *callInfo) {
175-
*md = c.headerMD
173+
if c.stream != nil {
174+
*md, _ = c.stream.Header()
175+
}
176176
})
177177
}
178178

179179
// Trailer returns a CallOptions that retrieves the trailer metadata
180180
// for a unary RPC.
181181
func Trailer(md *metadata.MD) CallOption {
182182
return afterCall(func(c *callInfo) {
183-
*md = c.trailerMD
183+
if c.stream != nil {
184+
*md = c.stream.Trailer()
185+
}
184186
})
185187
}
186188

187189
// Peer returns a CallOption that retrieves peer information for a
188190
// unary RPC.
189-
func Peer(peer *peer.Peer) CallOption {
191+
func Peer(p *peer.Peer) CallOption {
190192
return afterCall(func(c *callInfo) {
191-
if c.peer != nil {
192-
*peer = *c.peer
193+
if c.stream != nil {
194+
if x, ok := peer.FromContext(c.stream.Context()); ok {
195+
*p = *x
196+
}
193197
}
194198
})
195199
}

stream.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"google.golang.org/grpc/codes"
3131
"google.golang.org/grpc/encoding"
3232
"google.golang.org/grpc/metadata"
33-
"google.golang.org/grpc/peer"
3433
"google.golang.org/grpc/stats"
3534
"google.golang.org/grpc/status"
3635
"google.golang.org/grpc/transport"
@@ -253,10 +252,7 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
253252
break
254253
}
255254

256-
// Set callInfo.peer object from stream's context.
257-
if peer, ok := peer.FromContext(s.Context()); ok {
258-
c.peer = peer
259-
}
255+
c.stream = s
260256
cs := &clientStream{
261257
opts: opts,
262258
c: c,

0 commit comments

Comments
 (0)