From 1451c62ccdce325a1f2fdbcc90db89518a36dc06 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 4 Oct 2022 19:29:30 +0200 Subject: [PATCH] internal/transport: optimize grpc-message encoding/decoding (#5654) --- internal/transport/http_util.go | 21 ++++++++++----------- internal/transport/http_util_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/internal/transport/http_util.go b/internal/transport/http_util.go index d632dc4e812a..2c601a864d99 100644 --- a/internal/transport/http_util.go +++ b/internal/transport/http_util.go @@ -20,7 +20,6 @@ package transport import ( "bufio" - "bytes" "encoding/base64" "fmt" "io" @@ -251,13 +250,13 @@ func encodeGrpcMessage(msg string) string { } func encodeGrpcMessageUnchecked(msg string) string { - var buf bytes.Buffer + var sb strings.Builder for len(msg) > 0 { r, size := utf8.DecodeRuneInString(msg) for _, b := range []byte(string(r)) { if size > 1 { // If size > 1, r is not ascii. Always do percent encoding. - buf.WriteString(fmt.Sprintf("%%%02X", b)) + fmt.Fprintf(&sb, "%%%02X", b) continue } @@ -266,14 +265,14 @@ func encodeGrpcMessageUnchecked(msg string) string { // // fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD". if b >= spaceByte && b <= tildeByte && b != percentByte { - buf.WriteByte(b) + sb.WriteByte(b) } else { - buf.WriteString(fmt.Sprintf("%%%02X", b)) + fmt.Fprintf(&sb, "%%%02X", b) } } msg = msg[size:] } - return buf.String() + return sb.String() } // decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage. @@ -291,23 +290,23 @@ func decodeGrpcMessage(msg string) string { } func decodeGrpcMessageUnchecked(msg string) string { - var buf bytes.Buffer + var sb strings.Builder lenMsg := len(msg) for i := 0; i < lenMsg; i++ { c := msg[i] if c == percentByte && i+2 < lenMsg { parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8) if err != nil { - buf.WriteByte(c) + sb.WriteByte(c) } else { - buf.WriteByte(byte(parsed)) + sb.WriteByte(byte(parsed)) i += 2 } } else { - buf.WriteByte(c) + sb.WriteByte(c) } } - return buf.String() + return sb.String() } type bufWriter struct { diff --git a/internal/transport/http_util_test.go b/internal/transport/http_util_test.go index bbd53180471e..cc7807670b62 100644 --- a/internal/transport/http_util_test.go +++ b/internal/transport/http_util_test.go @@ -214,3 +214,27 @@ func (s) TestParseDialTarget(t *testing.T) { } } } + +func BenchmarkDecodeGrpcMessage(b *testing.B) { + input := "Hello, %E4%B8%96%E7%95%8C" + want := "Hello, 世界" + b.ReportAllocs() + for i := 0; i < b.N; i++ { + got := decodeGrpcMessage(input) + if got != want { + b.Fatalf("decodeGrpcMessage(%q) = %s, want %s", input, got, want) + } + } +} + +func BenchmarkEncodeGrpcMessage(b *testing.B) { + input := "Hello, 世界" + want := "Hello, %E4%B8%96%E7%95%8C" + b.ReportAllocs() + for i := 0; i < b.N; i++ { + got := encodeGrpcMessage(input) + if got != want { + b.Fatalf("encodeGrpcMessage(%q) = %s, want %s", input, got, want) + } + } +}