jsonplan: Improve performance for deep objects
When calculating the unknown values for JSON plan output, we would previously recursively call the `unknownAsBool` function on the current sub-tree twice, if any values were unknown. This was wasteful, but not noticeable for normal Terraform resource shapes. However for deeper nested object values, such as Kubernetes manifests, this was a severe performance problem, causing `terraform show -json` to take several hours to render a plan. This commit reuses the already calculated unknown value for the subtree, and adds benchmark coverage to demonstrate the improvement.
This commit is contained in:
parent
161374725c
commit
3e4d6b252f
|
@ -597,7 +597,7 @@ func unknownAsBool(val cty.Value) cty.Value {
|
||||||
// Omit all of the "false"s for known values for more compact
|
// Omit all of the "false"s for known values for more compact
|
||||||
// serialization
|
// serialization
|
||||||
if !vAsBool.RawEquals(cty.False) {
|
if !vAsBool.RawEquals(cty.False) {
|
||||||
vals[k.AsString()] = unknownAsBool(v)
|
vals[k.AsString()] = vAsBool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The above transform may have changed the types of some of the
|
// The above transform may have changed the types of some of the
|
||||||
|
|
|
@ -304,3 +304,59 @@ func TestEncodePaths(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deepObjectValue(depth int) cty.Value {
|
||||||
|
v := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal("a"),
|
||||||
|
"b": cty.NumberIntVal(2),
|
||||||
|
"c": cty.True,
|
||||||
|
"d": cty.UnknownVal(cty.String),
|
||||||
|
})
|
||||||
|
|
||||||
|
result := v
|
||||||
|
|
||||||
|
for i := 0; i < depth; i++ {
|
||||||
|
result = cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": result,
|
||||||
|
"b": result,
|
||||||
|
"c": result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnknownAsBool_2(b *testing.B) {
|
||||||
|
value := deepObjectValue(2)
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
unknownAsBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnknownAsBool_3(b *testing.B) {
|
||||||
|
value := deepObjectValue(3)
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
unknownAsBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnknownAsBool_5(b *testing.B) {
|
||||||
|
value := deepObjectValue(5)
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
unknownAsBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnknownAsBool_7(b *testing.B) {
|
||||||
|
value := deepObjectValue(7)
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
unknownAsBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnknownAsBool_9(b *testing.B) {
|
||||||
|
value := deepObjectValue(9)
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
unknownAsBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue