From 2ac40aec002b5588dbac3e6cd6a9970683852acd Mon Sep 17 00:00:00 2001 From: fujiwara Date: Tue, 17 Sep 2024 14:30:51 +0900 Subject: [PATCH 1/4] add benchmark goos: linux goarch: amd64 pkg: github.com/fujiwara/tfstate-lookup/tfstate cpu: AMD Ryzen 5 3400G with Radeon Vega Graphics BenchmarkLookupFile-8 3056 374179 ns/op 210225 B/op 2549 allocs/op PASS --- tfstate/lookup_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tfstate/lookup_test.go b/tfstate/lookup_test.go index 77a1c11..8ea1ef0 100644 --- a/tfstate/lookup_test.go +++ b/tfstate/lookup_test.go @@ -229,6 +229,25 @@ func TestLookupFileURL(t *testing.T) { testLookupState(t, state) } +func BenchmarkLookupFile(b *testing.B) { + f, err := os.Open("test/terraform.tfstate") + if err != nil { + b.Error(err) + } + state, err := tfstate.Read(context.Background(), f) + if err != nil { + b.Error(err) + } + for i := 0; i < b.N; i++ { + for _, ts := range TestSuitesOK { + _, err := state.Lookup(ts.Key) + if err != nil { + b.Error(err) + } + } + } +} + func TestLookupHTTPURL(t *testing.T) { h := http.FileServer(http.Dir(".")) ts := httptest.NewServer(h) From f4fcddc8975d1a36ece2e2353f02d785e27ac7bb Mon Sep 17 00:00:00 2001 From: fujiwara Date: Tue, 17 Sep 2024 14:32:47 +0900 Subject: [PATCH 2/4] regexp.MustCompile outside in the function goos: linux goarch: amd64 pkg: github.com/fujiwara/tfstate-lookup/tfstate cpu: AMD Ryzen 5 3400G with Radeon Vega Graphics BenchmarkLookupFile-8 5895 197672 ns/op 109939 B/op 1171 allocs/op PASS --- tfstate/lookup.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tfstate/lookup.go b/tfstate/lookup.go index d6e3dc0..ecb3c5d 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -242,10 +242,13 @@ func (s *TFState) Lookup(key string) (*Object, error) { // we must quote them like `.outputs["repository-arn"]`. // // quoteJQQuery does it. +var ( + quoteSplitRegex = regexp.MustCompile(`[.\[\]]`) + quoteIndexRegex = regexp.MustCompile(`^-?[0-9]+$`) +) + func quoteJQQuery(query string) string { - splitRegex := regexp.MustCompile(`[.\[\]]`) - indexRegex := regexp.MustCompile(`^-?[0-9]+$`) - parts := splitRegex.Split(query, -1) + parts := quoteSplitRegex.Split(query, -1) parts_coalesced := make([]string, 0, len(parts)) for _, part := range parts { @@ -259,7 +262,7 @@ func quoteJQQuery(query string) string { for _, part := range parts_coalesced { builder.WriteByte('[') - if indexRegex.MatchString(part) { + if quoteIndexRegex.MatchString(part) { builder.WriteString(part) } else { if !strings.HasPrefix(part, `"`) { From 2ceb58a4f7c8ad7fe90554c666750023029a3a16 Mon Sep 17 00:00:00 2001 From: fujiwara Date: Tue, 17 Sep 2024 14:57:48 +0900 Subject: [PATCH 3/4] short cut --- tfstate/lookup.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tfstate/lookup.go b/tfstate/lookup.go index ecb3c5d..678aca0 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -248,6 +248,10 @@ var ( ) func quoteJQQuery(query string) string { + if query == "" || !strings.Contains(query, "-") { + // short-circuit if query is empty or doesn't contain hyphen + return query + } parts := quoteSplitRegex.Split(query, -1) parts_coalesced := make([]string, 0, len(parts)) From 485732aa8f250f19f9929226bbdf8d06ba43f900 Mon Sep 17 00:00:00 2001 From: fujiwara Date: Tue, 17 Sep 2024 15:19:37 +0900 Subject: [PATCH 4/4] simplify goos: linux goarch: amd64 pkg: github.com/fujiwara/tfstate-lookup/tfstate cpu: AMD Ryzen 5 3400G with Radeon Vega Graphics BenchmarkLookupFile-8 7789 143841 ns/op 89158 B/op 854 allocs/op PASS --- tfstate/lookup.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/tfstate/lookup.go b/tfstate/lookup.go index 678aca0..c9dc279 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -253,18 +253,13 @@ func quoteJQQuery(query string) string { return query } parts := quoteSplitRegex.Split(query, -1) - parts_coalesced := make([]string, 0, len(parts)) - - for _, part := range parts { - if part != "" { - parts_coalesced = append(parts_coalesced, part) - } - } - var builder strings.Builder + builder.Grow(len(query) + 5*len(parts)) builder.WriteByte('.') - - for _, part := range parts_coalesced { + for _, part := range parts { + if part == "" { + continue + } builder.WriteByte('[') if quoteIndexRegex.MatchString(part) { builder.WriteString(part) @@ -272,9 +267,7 @@ func quoteJQQuery(query string) string { if !strings.HasPrefix(part, `"`) { builder.WriteByte('"') } - builder.WriteString(part) - if !strings.HasSuffix(part, `"`) { builder.WriteByte('"') }