|
|
@@ -279,10 +279,18 @@ type bufioEncWriter struct {
|
|
|
buf []byte
|
|
|
w io.Writer
|
|
|
n int
|
|
|
+ sz int // buf size
|
|
|
+
|
|
|
+ // Extensions can call Encode() within a current Encode() call.
|
|
|
+ // We need to know when the top level Encode() call returns,
|
|
|
+ // so we can decide whether to Release() or not.
|
|
|
+ calls uint16 // what depth in mustDecode are we in now.
|
|
|
+
|
|
|
+ _ [6]uint8 // padding
|
|
|
|
|
|
bytesBufPooler
|
|
|
|
|
|
- _ [3]uint64 // padding
|
|
|
+ _ [1]uint64 // padding
|
|
|
// a int
|
|
|
// b [4]byte
|
|
|
// err
|
|
|
@@ -291,20 +299,24 @@ type bufioEncWriter struct {
|
|
|
func (z *bufioEncWriter) reset(w io.Writer, bufsize int) {
|
|
|
z.w = w
|
|
|
z.n = 0
|
|
|
+ z.calls = 0
|
|
|
if bufsize <= 0 {
|
|
|
bufsize = defEncByteBufSize
|
|
|
}
|
|
|
- if z.buf == nil {
|
|
|
- z.buf = z.bytesBufPooler.get(bufsize)
|
|
|
- } else if cap(z.buf) >= bufsize {
|
|
|
+ z.sz = bufsize
|
|
|
+ if cap(z.buf) >= bufsize {
|
|
|
z.buf = z.buf[:cap(z.buf)]
|
|
|
} else {
|
|
|
- z.bytesBufPooler.end() // potentially return old one to pool
|
|
|
z.buf = z.bytesBufPooler.get(bufsize)
|
|
|
// z.buf = make([]byte, bufsize)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func (z *bufioEncWriter) release() {
|
|
|
+ z.buf = nil
|
|
|
+ z.bytesBufPooler.end()
|
|
|
+}
|
|
|
+
|
|
|
//go:noinline - flush only called intermittently
|
|
|
func (z *bufioEncWriter) flush() {
|
|
|
n, err := z.w.Write(z.buf[:z.n])
|
|
|
@@ -1237,12 +1249,7 @@ type Encoder struct {
|
|
|
|
|
|
ci set
|
|
|
|
|
|
- // Extensions can call Encode() within a current Encode() call.
|
|
|
- // We need to know when the top level Encode() call returns,
|
|
|
- // so we can decide whether to Release() or not.
|
|
|
- calls uint16 // what depth in mustEncode are we in now.
|
|
|
-
|
|
|
- b [(5 * 8) - 2]byte // for encoding chan or (non-addressable) [N]byte
|
|
|
+ b [(5 * 8)]byte // for encoding chan or (non-addressable) [N]byte
|
|
|
|
|
|
// ---- writable fields during execution --- *try* to keep in sep cache line
|
|
|
|
|
|
@@ -1298,7 +1305,6 @@ func (e *Encoder) resetCommon() {
|
|
|
_, e.js = e.hh.(*JsonHandle)
|
|
|
e.e.reset()
|
|
|
e.err = nil
|
|
|
- e.calls = 0
|
|
|
}
|
|
|
|
|
|
// Reset resets the Encoder with a new output stream.
|
|
|
@@ -1473,23 +1479,26 @@ func (e *Encoder) MustEncode(v interface{}) {
|
|
|
}
|
|
|
|
|
|
func (e *Encoder) mustEncode(v interface{}) {
|
|
|
- // ensure the bufioEncWriter buffer is not nil (e.g. if Release() was called)
|
|
|
- if e.wf != nil && e.wf.buf == nil {
|
|
|
- if e.h.WriterBufferSize > 0 {
|
|
|
- e.wf.buf = e.wf.bytesBufPooler.get(e.h.WriterBufferSize)
|
|
|
- } else {
|
|
|
- e.wf.buf = e.wf.bytesBufPooler.get(defEncByteBufSize)
|
|
|
- }
|
|
|
+ if e.wf == nil {
|
|
|
+ e.encode(v)
|
|
|
+ e.e.atEndOfEncode()
|
|
|
+ e.w.end()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if e.wf.buf == nil {
|
|
|
+ e.wf.buf = e.wf.bytesBufPooler.get(e.wf.sz)
|
|
|
}
|
|
|
+ e.wf.calls++
|
|
|
|
|
|
- e.calls++
|
|
|
e.encode(v)
|
|
|
e.e.atEndOfEncode()
|
|
|
e.w.end()
|
|
|
- e.calls--
|
|
|
|
|
|
- if !e.h.ExplicitRelease && e.calls == 0 {
|
|
|
- e.Release()
|
|
|
+ e.wf.calls--
|
|
|
+
|
|
|
+ if !e.h.ExplicitRelease && e.wf.calls == 0 {
|
|
|
+ e.wf.release()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1514,12 +1523,8 @@ func (e *Encoder) finalize() {
|
|
|
// It is important to call Release() when done with an Encoder, so those resources
|
|
|
// are released instantly for use by subsequently created Encoders.
|
|
|
func (e *Encoder) Release() {
|
|
|
- if useFinalizers && removeFinalizerOnRelease {
|
|
|
- runtime.SetFinalizer(e, nil)
|
|
|
- }
|
|
|
if e.wf != nil {
|
|
|
- e.wf.buf = nil
|
|
|
- e.wf.bytesBufPooler.end()
|
|
|
+ e.wf.release()
|
|
|
}
|
|
|
}
|
|
|
|