@@ -53,41 +53,70 @@ func (p *Parser) ParseBytes(b []byte) (*Value, error) {
53
53
}
54
54
55
55
type cache struct {
56
- vs [][]Value
57
- allocated int
56
+ vs []Value
57
+ nx * cache // next
58
+ lt * cache // last
58
59
}
59
60
60
61
func (c * cache ) reset () {
61
- for i := range c .vs {
62
- c .vs [i ] = c .vs [i ][:0 ]
63
- }
64
62
c .vs = c .vs [:0 ]
63
+ c .lt = nil
64
+ if c .nx != nil {
65
+ c .nx .reset ()
66
+ }
65
67
}
66
68
67
- const preAllocatedCacheSize = 32768
69
+ const (
70
+ preAllocatedCacheSize = 409 // 32kb class size
71
+ macAllocatedCacheSize = 1024
72
+ )
68
73
69
74
func (c * cache ) getValue () * Value {
70
- last := len (c .vs ) - 1
71
- needExt := last < 0 || cap (c .vs [last ]) == len (c .vs [last ])
72
- for {
73
- if needExt {
74
- if cap (c .vs ) > len (c .vs ) {
75
- c .vs = c .vs [:len (c .vs )+ 1 ]
76
- } else {
77
- c .vs = append (c .vs , make ([]Value , 0 , preAllocatedCacheSize ))
78
- }
79
- last = len (c .vs ) - 1
80
- needExt = false
75
+ var (
76
+ addNext bool
77
+ readSrc = c
78
+ )
79
+ switch {
80
+ case cap (c .vs ) == 0 :
81
+ // initial state
82
+ c .vs = make ([]Value , 1 , preAllocatedCacheSize )
83
+
84
+ case c .lt != nil :
85
+ l := c .lt
86
+ if cap (l .vs ) > len (l .vs ) {
87
+ l .vs = l .vs [:len (l .vs )+ 1 ]
88
+ readSrc = l
89
+ break
90
+ }
91
+ addNext = true
92
+
93
+ default :
94
+ if cap (c .vs ) > len (c .vs ) {
95
+ c .vs = c .vs [:len (c .vs )+ 1 ]
96
+ break
97
+ }
98
+ addNext = true
99
+ }
100
+ if addNext {
101
+ nextSize := len (c .vs )
102
+ if nextSize * 2 < macAllocatedCacheSize {
103
+ nextSize *= 2
104
+ } else {
105
+ nextSize = macAllocatedCacheSize
81
106
}
82
- if cap (c .vs [last ]) > len (c .vs [last ]) {
83
- c .vs [last ] = c .vs [last ][:len (c .vs [last ])+ 1 ]
107
+ readSrc = & cache {
108
+ vs : make ([]Value , 1 , nextSize ),
109
+ }
110
+ if c .lt != nil {
111
+ c .lt .nx = readSrc
112
+ c .lt = c .lt .nx
84
113
} else {
85
- needExt = true
86
- continue
114
+ c . nx = readSrc
115
+ c . lt = c . nx
87
116
}
88
- // Do not reset the value, since the caller must properly init it.
89
- return & c .vs [last ][len (c .vs [last ])- 1 ]
90
117
}
118
+ // Do not reset the value, since the caller must properly init it.
119
+ return & readSrc .vs [len (readSrc .vs )- 1 ]
91
120
}
92
121
93
122
func skipWS (s string ) string {
0 commit comments