From f725b988fe6746cfab6516ab97ee13dc90471856 Mon Sep 17 00:00:00 2001 From: Sylvain Rabot Date: Wed, 17 Jul 2024 22:00:28 +0200 Subject: [PATCH] Optimize tag value parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: darwin goarch: arm64 pkg: github.com/quickfixgo/quickfix │ old │ new-no-indexbyte │ │ sec/op │ sec/op vs base │ ParseMessage-8 695.2n ± 1% 628.2n ± 1% -9.64% (p=0.000 n=20) ``` Signed-off-by: Sylvain Rabot --- tag_value.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tag_value.go b/tag_value.go index 6e721862f..28bba7a7a 100644 --- a/tag_value.go +++ b/tag_value.go @@ -39,8 +39,28 @@ func (tv *TagValue) init(tag Tag, value []byte) { } func (tv *TagValue) parse(rawFieldBytes []byte) error { - sepIndex := bytes.IndexByte(rawFieldBytes, '=') + var sepIndex int + // Most of the Fix tags are 4 or less characters long, so we can optimize + // for that by checking the 5 first characters without looping over the + // whole byte slice. + if len(rawFieldBytes) >= 5 { + if rawFieldBytes[1] == '=' { + sepIndex = 1 + goto PARSE + } else if rawFieldBytes[2] == '=' { + sepIndex = 2 + goto PARSE + } else if rawFieldBytes[3] == '=' { + sepIndex = 3 + goto PARSE + } else if rawFieldBytes[4] == '=' { + sepIndex = 4 + goto PARSE + } + } + + sepIndex = bytes.IndexByte(rawFieldBytes, '=') switch sepIndex { case -1: return fmt.Errorf("tagValue.Parse: No '=' in '%s'", rawFieldBytes) @@ -48,6 +68,7 @@ func (tv *TagValue) parse(rawFieldBytes []byte) error { return fmt.Errorf("tagValue.Parse: No tag in '%s'", rawFieldBytes) } +PARSE: parsedTag, err := atoi(rawFieldBytes[:sepIndex]) if err != nil { return fmt.Errorf("tagValue.Parse: %s", err.Error())