diff --git a/.changes/unreleased/BUG FIXES-20230703-123518.yaml b/.changes/unreleased/BUG FIXES-20230703-123518.yaml new file mode 100644 index 00000000..05e6c9cb --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20230703-123518.yaml @@ -0,0 +1,6 @@ +kind: BUG FIXES +body: 'types/basetypes: Minor reduction of memory allocations for `ObjectValue` type + `ToTerraformValue()` method, which decreases provider operation durations at scale' +time: 2023-07-03T12:35:18.484275-04:00 +custom: + Issue: "775" diff --git a/types/basetypes/object_value.go b/types/basetypes/object_value.go index 1a965dac..baeb8c0e 100644 --- a/types/basetypes/object_value.go +++ b/types/basetypes/object_value.go @@ -262,10 +262,12 @@ func (o ObjectValue) Type(ctx context.Context) attr.Type { // ToTerraformValue returns the data contained in the attr.Value as // a tftypes.Value. func (o ObjectValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { - attrTypes := map[string]tftypes.Type{} - for attr, typ := range o.AttributeTypes(ctx) { + attrTypes := make(map[string]tftypes.Type, len(o.attributeTypes)) + + for attr, typ := range o.attributeTypes { attrTypes[attr] = typ.TerraformType(ctx) } + objectType := tftypes.Object{AttributeTypes: attrTypes} switch o.state { diff --git a/types/basetypes/object_value_test.go b/types/basetypes/object_value_test.go index cafc1fb3..0801081d 100644 --- a/types/basetypes/object_value_test.go +++ b/types/basetypes/object_value_test.go @@ -6,6 +6,7 @@ package basetypes import ( "context" "math/big" + "strconv" "testing" "github.com/google/go-cmp/cmp" @@ -15,6 +16,35 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" ) +func BenchmarkObjectValueToTerraformValue1000(b *testing.B) { + benchmarkObjectValueToTerraformValue(b, 1000) +} + +func benchmarkObjectValueToTerraformValue(b *testing.B, attributes int) { + attributeTypes := make(map[string]attr.Type, attributes) + attributeValues := make(map[string]attr.Value, attributes) + ctx := context.Background() + + for i := 0; i < attributes; i++ { + attributeName := "testattr" + strconv.Itoa(i) + attributeTypes[attributeName] = BoolType{} + attributeValues[attributeName] = NewBoolNull() + } + + value := NewObjectValueMust( + attributeTypes, + attributeValues, + ) + + for n := 0; n < b.N; n++ { + _, err := value.ToTerraformValue(ctx) + + if err != nil { + b.Fatalf("unexpected ToTerraformValue error: %s", err) + } + } +} + func TestNewObjectValue(t *testing.T) { t.Parallel()