From 79865b10ef9b089d2f7d679ce50d2c932c99a4f8 Mon Sep 17 00:00:00 2001 From: James Samunderu Date: Tue, 28 Apr 2020 23:08:56 +0200 Subject: [PATCH] Avoid unnecessary memory allocations in decodeMapFromStruct Splits allocates memory. This burdens the garbage collector. By using string.Index to parse string you will be more cache aware and do not create gabbage. --- mapstructure.go | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/mapstructure.go b/mapstructure.go index cc456138..5e9408d3 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -840,42 +840,31 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re } tagValue := f.Tag.Get(d.config.TagName) - tagParts := strings.Split(tagValue, ",") - - // If "omitempty" is specified in the tag, it ignores empty values. - omitempty := false - for _, tag := range tagParts[1:] { - if tag == "omitempty" { - omitempty = true - break - } - } - if omitempty && isEmptyValue(v) { - continue - } - - // Determine the name of the key in the map keyName := f.Name - if tagParts[0] != "" { - if tagParts[0] == "-" { - continue - } - keyName = tagParts[0] - } // If Squash is set in the config, we squash the field down. squash := d.config.Squash && v.Kind() == reflect.Struct - // If "squash" is specified in the tag, we squash the field down. - if !squash { - for _, tag := range tagParts[1:] { - if tag == "squash" { - squash = true - break - } + // Determine the name of the key in the map + if index := strings.Index(tagValue, ","); index != -1 { + if tagValue[:index] == "-" { + continue; } + // If "omitempty" is specified in the tag, it ignores empty values. + if strings.Index(tagValue[index + 1:], "omitempty") != -1 && isEmptyValue(v) { + continue + } + + // If "squash" is specified in the tag, we squash the field down. + squash = !squash && strings.Index(tagValue[index + 1:], "squash") != -1 if squash && v.Kind() != reflect.Struct { return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) } + keyName = tagValue[:index] + } else if len(tagValue) > 0 { + if tagValue == "-" { + continue + } + keyName = tagValue } switch v.Kind() { @@ -1226,9 +1215,8 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } // Build our field - fieldCurrent := field{fieldType, structVal.Field(i)} if remain { - remainField = &fieldCurrent + remainField = &field{fieldType, structVal.Field(i)} } else { // Normal struct field, store it away fields = append(fields, field{fieldType, structVal.Field(i)})