diff options
| author | Shulhan <m.shulhan@gmail.com> | 2024-01-25 04:23:24 +0700 |
|---|---|---|
| committer | Shulhan <m.shulhan@gmail.com> | 2026-04-14 21:51:40 +0700 |
| commit | 779b2c6eaca78a60f8e42ebc8a7c47c149f3a9cc (patch) | |
| tree | e5b79ad04cdec310dd53a2c2de5827366d79aa0b | |
| parent | 7ace40ec22f23a9df78fdbee54fc44e6e30fb1dc (diff) | |
| download | go-779b2c6eaca78a60f8e42ebc8a7c47c149f3a9cc.tar.xz | |
encoding/json: realign struct encodeState, structFields, and field
This reduce the struct encodeState size from 56 to 16 bytes (-42),
struct structFields size from 40 to 24 bytes (-16), and struct field size
from 136 to 128 bytes (-8).
Benchmark memory profiling before and after,
File: json.test
Type: alloc_space
Time: Jan 25, 2024 at 4:51am (WIB)
Showing nodes accounting for -4.01GB, 4.66% of 85.95GB total
Dropped 64 nodes (cum <= 0.43GB)
flat flat% sum% cum cum%
-4.25GB 4.94% 4.94% -4.01GB 4.67% encoding/json.Marshal
0.19GB 0.22% 4.73% 0.24GB 0.28% encoding/json.mapEncoder.encode
0.05GB 0.057% 4.67% 0.05GB 0.057% reflect.copyVal
0.04GB 0.049% 4.62% 0.04GB 0.049% bytes.growSlice
-0.04GB 0.045% 4.66% -0.04GB 0.045% encoding/json.RawMessage.MarshalJSON
0 0% 4.66% 0.04GB 0.046% bytes.(*Buffer).WriteString
0 0% 4.66% 0.04GB 0.049% bytes.(*Buffer).grow
0 0% 4.66% -0.04GB 0.045% encoding/json.(*Encoder).Encode
0 0% 4.66% 0.20GB 0.23% encoding/json.(*encodeState).marshal
0 0% 4.66% 0.20GB 0.23% encoding/json.(*encodeState).reflectValue
| -rw-r--r-- | src/encoding/json/encode.go | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 5e47413f23..0cca15b6e0 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -296,6 +296,8 @@ const hex = "0123456789abcdef" // An encodeState encodes JSON into a bytes.Buffer. type encodeState struct { + ptrSeen map[any]struct{} + bytes.Buffer // accumulated output // Keep track of what pointers we've seen in the current recursive call @@ -304,7 +306,6 @@ type encodeState struct { // startDetectingCyclesAfter, so that we skip the work if we're within a // reasonable amount of nested pointers deep. ptrLevel uint - ptrSeen map[any]struct{} } const startDetectingCyclesAfter = 1000 @@ -710,9 +711,9 @@ type structEncoder struct { } type structFields struct { - list []field byExactName map[string]*field byFoldedName map[string]*field + list []field } func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { @@ -1068,21 +1069,22 @@ func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) // A field represents a single field found in a struct. type field struct { - name string - nameBytes []byte // []byte(name) + encoder encoderFunc + + typ reflect.Type + name string nameNonEsc string // `"` + name + `":` nameEscHTML string // `"` + HTMLEscape(name) + `":` - tag bool index []int - typ reflect.Type + nameBytes []byte // []byte(name) + + tag bool omitEmpty bool omitZero bool isZero func(reflect.Value) bool quoted bool - - encoder encoderFunc } type isZeroer interface { @@ -1308,7 +1310,7 @@ func typeFields(t reflect.Type) structFields { foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i] } } - return structFields{fields, exactNameIndex, foldedNameIndex} + return structFields{exactNameIndex, foldedNameIndex, fields} } // dominantField looks through the fields, all of which are known to |
