memoize DiffFieldReader.ReadField
The field reader code path is extremely inefficient, but refactoring it all is much to invasive a change at the moment. Have DiffFieldReader internally cache results for ReadField.
This commit is contained in:
parent
870617d22d
commit
ca68723c91
|
@ -29,29 +29,59 @@ type DiffFieldReader struct {
|
||||||
Diff *terraform.InstanceDiff
|
Diff *terraform.InstanceDiff
|
||||||
Source FieldReader
|
Source FieldReader
|
||||||
Schema map[string]*Schema
|
Schema map[string]*Schema
|
||||||
|
|
||||||
|
// cache for memoizing ReadField calls.
|
||||||
|
cache map[string]cachedFieldReadResult
|
||||||
|
}
|
||||||
|
|
||||||
|
type cachedFieldReadResult struct {
|
||||||
|
val FieldReadResult
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
||||||
|
if r.cache == nil {
|
||||||
|
r.cache = make(map[string]cachedFieldReadResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the cache key by joining around a value that isn't a valid part
|
||||||
|
// of an address. This assumes that the Source and Schema are not changed
|
||||||
|
// for the life of this DiffFieldReader.
|
||||||
|
cacheKey := strings.Join(address, "|")
|
||||||
|
if cached, ok := r.cache[cacheKey]; ok {
|
||||||
|
return cached.val, cached.err
|
||||||
|
}
|
||||||
|
|
||||||
schemaList := addrToSchema(address, r.Schema)
|
schemaList := addrToSchema(address, r.Schema)
|
||||||
if len(schemaList) == 0 {
|
if len(schemaList) == 0 {
|
||||||
|
r.cache[cacheKey] = cachedFieldReadResult{}
|
||||||
return FieldReadResult{}, nil
|
return FieldReadResult{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var res FieldReadResult
|
||||||
|
var err error
|
||||||
|
|
||||||
schema := schemaList[len(schemaList)-1]
|
schema := schemaList[len(schemaList)-1]
|
||||||
switch schema.Type {
|
switch schema.Type {
|
||||||
case TypeBool, TypeInt, TypeFloat, TypeString:
|
case TypeBool, TypeInt, TypeFloat, TypeString:
|
||||||
return r.readPrimitive(address, schema)
|
res, err = r.readPrimitive(address, schema)
|
||||||
case TypeList:
|
case TypeList:
|
||||||
return readListField(r, address, schema)
|
res, err = readListField(r, address, schema)
|
||||||
case TypeMap:
|
case TypeMap:
|
||||||
return r.readMap(address, schema)
|
res, err = r.readMap(address, schema)
|
||||||
case TypeSet:
|
case TypeSet:
|
||||||
return r.readSet(address, schema)
|
res, err = r.readSet(address, schema)
|
||||||
case typeObject:
|
case typeObject:
|
||||||
return readObjectField(r, address, schema.Elem.(map[string]*Schema))
|
res, err = readObjectField(r, address, schema.Elem.(map[string]*Schema))
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("Unknown type: %#v", schema.Type))
|
panic(fmt.Sprintf("Unknown type: %#v", schema.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.cache[cacheKey] = cachedFieldReadResult{
|
||||||
|
val: res,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DiffFieldReader) readMap(
|
func (r *DiffFieldReader) readMap(
|
||||||
|
|
Loading…
Reference in New Issue