本文對比試驗採用官方包作json map 和struct 編碼。原文鏈接:http://blog.lpflpf.cn/passage...linux
map 數據類型爲map[string]string , key 長度爲10, val 長度爲100
struct 定義以下:git
type Object struct { Xvlbzgbaic string `json:"xvlbzgbaic"` Krbemfdzdc string `json:"krbemfdzdc"` Rzlntxyeuc string `json:"rzlntxyeuc"` Ctzkjkziva string `json:"ctzkjkziva"` Orsufumaps string `json:"orsufumaps"` Hyevwbtcml string `json:"hyevwbtcml"` Baatlyhdao string `json:"baatlyhdao"` Fkfohsvvxs string `json:"fkfohsvvxs"` Pqwarpxptp string `json:"pqwarpxptp"` Orvaukawww string `json:"orvaukawww"` }
對比程序以下:github
obj := Object{} json.Unmarshal([]byte(str), &obj) start := time.Now() for i := 0; i < 1000000; i++ { json.Marshal(obj) } fmt.Println(time.Since(start)) maps := map[string]string{} json.Unmarshal([]byte(str), &maps) start = time.Now() for i := 0; i < 1000000; i++ { json.Marshal(maps) } // fmt.Println(time.Since(start))
其中,str 爲生成好的固定json數據, 咱們對相同的數據作json 編碼, 運行結果能夠看出,時間差距大約爲1倍,若將map的key 個數調整爲100個golang
運行次數均爲1000,000 次json
type\ keys 個數 | 10 | 100 | 1000 |
---|---|---|---|
struct | 3.84s | 33.72s | 5m42.34s |
map[string]string | 7.59s | 1m20.03s | 17m21.47s |
no sorting map[string]string | 6.40s | 57.61s | 10m4.39s |
從上述對比中,得出以下結論:
在大量使用json 編碼時(尤爲是map結構較大時),請注意儘可能直接用struct,而不是用map作編碼。
map 編碼問題緩存
// go/src/encoding/json/encode.go func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { if v.IsNil() { e.WriteString("null") return } e.WriteByte('{') // Extract and sort the keys. keys := v.MapKeys() sv := make([]reflectWithString, len(keys)) for i, v := range keys { sv[i].v = v if err := sv[i].resolve(); err != nil { e.error(&MarshalerError{v.Type(), err}) } } // 在輸出前會作key 的排序,最後按照key 排序的結果作輸出 sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s }) for i, kv := range sv { if i > 0 { e.WriteByte(',') } e.string(kv.s, opts.escapeHTML) e.WriteByte(':') me.elemEnc(e, v.MapIndex(kv.v), opts) } e.WriteByte('}') }
// go/src/encoding/json/encode.go type structEncoder struct { fields []field fieldEncs []encoderFunc } func newStructEncoder(t reflect.Type) encoderFunc { fields := cachedTypeFields(t) // 從cache 中獲取fields se := &structEncoder{ fields: fields, fieldEncs: make([]encoderFunc, len(fields)), } for i, f := range fields { se.fieldEncs[i] = typeEncoder(typeByIndex(t, f.index)) } return se.encode } func (se *structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { e.WriteByte('{') first := true for i, f := range se.fields { // fields 被緩存在structEncoder 結構體中 fv := fieldByIndex(v, f.index) if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) { continue } if first { first = false } else { e.WriteByte(',') } e.string(f.name, opts.escapeHTML) e.WriteByte(':') opts.quoted = f.quoted se.fieldEncs[i](e, fv, opts) } e.WriteByte('}') }
根據上述內容,對比github.com/json-iterator/go 與 encoding/json 的對比試驗,也能夠看出,iterator 對 map 的性能提高不是很明顯(因爲都須要作反射),後續將作試驗驗證。性能