diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f1f4207..3ba89bd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.16.x + go-version: 1.18.x - name: Checkout code uses: actions/checkout@v3 diff --git a/gabs.go b/gabs.go index b846954..5e0ce14 100644 --- a/gabs.go +++ b/gabs.go @@ -31,6 +31,8 @@ import ( "os" "strconv" "strings" + + lru "github.com/hashicorp/golang-lru/v2" ) //------------------------------------------------------------------------------ @@ -79,11 +81,17 @@ var ( var ( r1 *strings.Replacer r2 *strings.Replacer + // Cache for DotPathToSlice + dotPathCache *lru.Cache[string, []string] + // Cache for JSONPointerToSlice + jsonPointerCache *lru.Cache[string, []string] ) func init() { r1 = strings.NewReplacer("~1", "/", "~0", "~") r2 = strings.NewReplacer("~1", ".", "~0", "~") + dotPathCache, _ = lru.New[string, []string](1024) + jsonPointerCache, _ = lru.New[string, []string](1024) } //------------------------------------------------------------------------------ @@ -105,10 +113,20 @@ func JSONPointerToSlice(path string) ([]string, error) { if path == "/" { return []string{""}, nil } + + item, ok := jsonPointerCache.Get(path) + + if ok { + return item, nil + } + hierarchy := strings.Split(path, "/")[1:] for i, v := range hierarchy { hierarchy[i] = r1.Replace(v) } + + jsonPointerCache.Add(path, hierarchy) + return hierarchy, nil } @@ -118,10 +136,20 @@ func JSONPointerToSlice(path string) ([]string, error) { // if it appears in the reference key. Likewise, '~' (%x7E) must be encoded // as '~0' since it is the escape character for encoding '.'. func DotPathToSlice(path string) []string { + item, ok := dotPathCache.Get(path) + + if ok { + return item + } + hierarchy := strings.Split(path, ".") + for i, v := range hierarchy { hierarchy[i] = r2.Replace(v) } + + dotPathCache.Add(path, hierarchy) + return hierarchy } diff --git a/gabs_test.go b/gabs_test.go index f8429e5..29506d2 100644 --- a/gabs_test.go +++ b/gabs_test.go @@ -1950,3 +1950,37 @@ func BenchmarkWildcardSearch(b *testing.B) { val.Search([]string{"test", "*", "value"}...) } } + +func BenchmarkJsonPointerToSlice(b *testing.B) { + samples := []string{ + "/test/field", + "/field/test", + "/user/name", + "/user/email/address", + "/host/ip/addres", + "/host/os/family", + "/host/os/version", + "/test/field", + "/field/test", + "/user/name", + "/user/email/address", + "/host/ip/addres", + "/host/os/family", + "/host/os/version", + "/test/field", + "/field/test", + "/user/name", + "/user/email/address", + "/host/ip/addres", + "/host/os/family", + "/host/os/version", + } + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + for _, s := range samples { + JSONPointerToSlice(s) + } + } +} diff --git a/go.mod b/go.mod index bd75790..a791483 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/Jeffail/gabs/v2 -go 1.16 +go 1.18 + +require github.com/hashicorp/golang-lru/v2 v2.0.2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..8f2fb76 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=