@@ -54,20 +54,80 @@ func (p *Parser) ParseBytes(b []byte) (*Value, error) {
54
54
55
55
type cache struct {
56
56
vs []Value
57
+ nx * cache // next
58
+ lt * cache // last
57
59
}
58
60
59
61
func (c * cache ) reset () {
60
62
c .vs = c .vs [:0 ]
63
+ c .lt = nil
64
+ if c .nx != nil {
65
+ c .nx .reset ()
66
+ }
61
67
}
62
68
69
+ const (
70
+ preAllocatedCacheSize = 409 // 32kb class size
71
+ macAllocatedCacheSize = 1024
72
+ )
73
+
63
74
func (c * cache ) getValue () * Value {
64
- if cap (c .vs ) > len (c .vs ) {
65
- c .vs = c .vs [:len (c .vs )+ 1 ]
66
- } else {
67
- c .vs = append (c .vs , Value {})
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
+ switch {
102
+ case c .lt != nil && c .lt .nx != nil :
103
+ c .lt = c .lt .nx
104
+ readSrc = c .lt
105
+ readSrc .vs = readSrc .vs [:1 ]
106
+ case c .lt == nil && c .nx != nil :
107
+ c .lt = c .nx
108
+ readSrc = c .lt
109
+ readSrc .vs = readSrc .vs [:1 ]
110
+ default :
111
+ nextSize := len (c .vs )
112
+ if nextSize * 2 < macAllocatedCacheSize {
113
+ nextSize *= 2
114
+ } else {
115
+ nextSize = macAllocatedCacheSize
116
+ }
117
+ readSrc = & cache {
118
+ vs : make ([]Value , 1 , nextSize ),
119
+ }
120
+ if c .lt != nil {
121
+ c .lt .nx = readSrc
122
+ c .lt = c .lt .nx
123
+ } else {
124
+ c .nx = readSrc
125
+ c .lt = c .nx
126
+ }
127
+ }
68
128
}
69
129
// Do not reset the value, since the caller must properly init it.
70
- return & c .vs [len (c .vs )- 1 ]
130
+ return & readSrc .vs [len (readSrc .vs )- 1 ]
71
131
}
72
132
73
133
func skipWS (s string ) string {
0 commit comments