From 5cea53af26cd0cb531fa87f9b78b4dfb43994de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Tue, 8 Jul 2025 15:50:59 +0200 Subject: [PATCH] perf(constants): avoid allocating a map for each Decode*() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: github.com/ucan-wg/go-varsig cpu: 13th Gen Intel(R) Core(TM) i7-1360P │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ DecodeHashAlgorithm-16 145.65n ± 10% 59.62n ± 30% -59.07% (p=0.000 n=10) DecodePayloadEncoding-16 136.65n ± 46% 50.02n ± 5% -63.40% (p=0.000 n=10) geomean 141.1n 54.60n -61.29% │ old.txt │ new.txt │ │ B/op │ B/op vs base │ DecodeHashAlgorithm-16 48.00 ± 0% 48.00 ± 0% ~ (p=1.000 n=10) ¹ DecodePayloadEncoding-16 48.00 ± 0% 48.00 ± 0% ~ (p=1.000 n=10) ¹ geomean 48.00 48.00 +0.00% ¹ all samples are equal │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ DecodeHashAlgorithm-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ DecodePayloadEncoding-16 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ geomean 1.000 1.000 +0.00% ¹ all samples are equal ``` --- constant.go | 51 +++++++++++++++++++++++------------------------- constant_test.go | 16 +++++++++++++++ 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/constant.go b/constant.go index baf4095..82621f4 100644 --- a/constant.go +++ b/constant.go @@ -12,7 +12,7 @@ import ( const Prefix = uint64(multicodec.Varsig) // HashAlgorithm is the multicodec.Code that specifies the hash algorithm -// that's used to reduced the signed content +// that's used to reduce the signed content type HashAlgorithm uint64 // Constant multicodec.Code values that allow Varsig implementations to @@ -36,16 +36,15 @@ func DecodeHashAlgorithm(r *bytes.Reader) (HashAlgorithm, error) { h := HashAlgorithm(u) - if _, ok := map[HashAlgorithm]struct{}{ - HashAlgorithmSHA256: {}, - HashAlgorithmSHA384: {}, - HashAlgorithmSHA512: {}, - HashAlgorithmShake256: {}, - }[h]; !ok { + switch h { + case HashAlgorithmSHA256, + HashAlgorithmSHA384, + HashAlgorithmSHA512, + HashAlgorithmShake256: + return h, nil + default: return HashAlgorithmUnspecified, fmt.Errorf("%w: %x", ErrUnknownHashAlgorithm, h) } - - return h, nil } // PayloadEncoding specifies the encoding of the data being (hashed and) @@ -88,32 +87,30 @@ func DecodePayloadEncoding(r *bytes.Reader, vers Version) (PayloadEncoding, erro // https://github.com/ChainAgnostic/varsig#4-payload-encoding func decodeEncodingInfoV0(payEnc PayloadEncoding) (PayloadEncoding, error) { - if _, ok := map[PayloadEncoding]struct{}{ - PayloadEncodingVerbatim: {}, - PayloadEncodingDAGPB: {}, - PayloadEncodingDAGCBOR: {}, - PayloadEncodingDAGJSON: {}, - PayloadEncodingJWT: {}, - PayloadEncodingEIP191: {}, - }[payEnc]; !ok { + switch payEnc { + case PayloadEncodingVerbatim, + PayloadEncodingDAGPB, + PayloadEncodingDAGCBOR, + PayloadEncodingDAGJSON, + PayloadEncodingJWT, + PayloadEncodingEIP191: + return payEnc, nil + default: return PayloadEncodingUnspecified, fmt.Errorf("%w: version=%d, encoding=%x", ErrUnsupportedPayloadEncoding, Version0, payEnc) } - - return payEnc, nil } // https://github.com/expede/varsig/blob/main/README.md#payload-encoding func decodeEncodingInfoV1(payEnc PayloadEncoding) (PayloadEncoding, error) { - if _, ok := map[PayloadEncoding]struct{}{ - PayloadEncodingVerbatim: {}, - PayloadEncodingDAGCBOR: {}, - PayloadEncodingDAGJSON: {}, - PayloadEncodingEIP191: {}, - }[payEnc]; !ok { + switch payEnc { + case PayloadEncodingVerbatim, + PayloadEncodingDAGCBOR, + PayloadEncodingDAGJSON, + PayloadEncodingEIP191: + return payEnc, nil + default: return PayloadEncodingUnspecified, fmt.Errorf("%w: version=%d, encoding=%x", ErrUnsupportedPayloadEncoding, Version1, payEnc) } - - return payEnc, nil } // Discriminator is (usually) the multicodec.Code representing the public diff --git a/constant_test.go b/constant_test.go index 7801e7e..78b5ee8 100644 --- a/constant_test.go +++ b/constant_test.go @@ -39,6 +39,14 @@ func TestDecodeHashAlgorithm(t *testing.T) { }) } +func BenchmarkDecodeHashAlgorithm(b *testing.B) { + b.ReportAllocs() + data := []byte{0x12} + for i := 0; i < b.N; i++ { + _, _ = varsig.DecodeHashAlgorithm(bytes.NewReader(data)) + } +} + func TestDecodePayloadEncoding(t *testing.T) { t.Parallel() @@ -105,3 +113,11 @@ func TestDecodePayloadEncoding(t *testing.T) { } }) } + +func BenchmarkDecodePayloadEncoding(b *testing.B) { + b.ReportAllocs() + data := []byte{0x5f} + for i := 0; i < b.N; i++ { + _, _ = varsig.DecodePayloadEncoding(bytes.NewReader(data), varsig.Version1) + } +}