Skip to content

Commit 3ecc97d

Browse files
committed
user: avoid full metadata copy in ExtractFromGRPCRequest
Use metadata.ValueFromIncomingContext to read only the x-scope-orgid key instead of metadata.FromIncomingContext which deep-copies the entire metadata map. FromIncomingContext copies every key-value pair in the metadata map on every call. With 10 metadata keys per request, this is 16 allocations and 1016 bytes per call. ValueFromIncomingContext only copies the single requested key's []string slice. Benchmark results (10 metadata keys): name old time/op new time/op delta ExtractFromGRPCRequest-48 1389ns ± 2% 135ns ± 1% -90.3% name old alloc/op new alloc/op delta ExtractFromGRPCRequest-48 1016B ± 0% 80B ± 0% -92.1% name old allocs/op new allocs/op delta ExtractFromGRPCRequest-48 16.0 ± 0% 3.0 ± 0% -81.2% Signed-off-by: Alan Protasio <approtas@amazon.com>
1 parent 0315015 commit 3ecc97d

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

user/grpc.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,8 @@ import (
88
// ExtractFromGRPCRequest extracts the user ID from the request metadata and returns
99
// the user ID and a context with the user ID injected.
1010
func ExtractFromGRPCRequest(ctx context.Context) (string, context.Context, error) {
11-
md, ok := metadata.FromIncomingContext(ctx)
12-
if !ok {
13-
return "", ctx, ErrNoOrgID
14-
}
15-
16-
orgIDs, ok := md[lowerOrgIDHeaderName]
17-
if !ok || len(orgIDs) != 1 {
11+
orgIDs := metadata.ValueFromIncomingContext(ctx, lowerOrgIDHeaderName)
12+
if len(orgIDs) != 1 {
1813
return "", ctx, ErrNoOrgID
1914
}
2015

user/grpc_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package user
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"google.golang.org/grpc/metadata"
8+
)
9+
10+
func BenchmarkExtractFromGRPCRequest(b *testing.B) {
11+
// Simulate a realistic incoming context with multiple metadata keys
12+
md := metadata.MD{
13+
"content-type": []string{"application/grpc"},
14+
"user-agent": []string{"grpc-go/1.71.2"},
15+
"x-scope-orgid": []string{"tenant-12345"},
16+
"x-forwarded-for": []string{"10.0.0.1"},
17+
"x-request-id": []string{"abc-def-ghi-jkl"},
18+
"traceparent": []string{"00-abcdef1234567890abcdef1234567890-1234567890abcdef-01"},
19+
"grpc-accept-encoding": []string{"gzip"},
20+
"authorization": []string{"Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."},
21+
"x-amz-date": []string{"20260507T183000Z"},
22+
"x-amz-security-token": []string{"FwoGZXIvYXdzEBYaDH..."},
23+
}
24+
ctx := metadata.NewIncomingContext(context.Background(), md)
25+
26+
b.ReportAllocs()
27+
b.ResetTimer()
28+
for i := 0; i < b.N; i++ {
29+
_, _, _ = ExtractFromGRPCRequest(ctx)
30+
}
31+
}

0 commit comments

Comments
 (0)