-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance issue when run Terraform Plan with many Block Sets or NestedAttribute Sets #775
Comments
Hi @jeremmfr 👋 Thank you for reporting this issue and sorry for the trouble here. I just wanted to acknowledge that the maintainers have noticed this bug report and do plan on taking a further look into this, but that effort will probably happen early next week. In the meantime, if you have any familiarity with |
Hi, I've run profiling with pprof, the provider I've also updated all the dependencies for the provider require (
github.com/hashicorp-demoapp/hashicups-client-go v0.1.0
- github.com/hashicorp/terraform-plugin-docs v0.14.1
- github.com/hashicorp/terraform-plugin-framework v1.2.0
- github.com/hashicorp/terraform-plugin-go v0.15.0
- github.com/hashicorp/terraform-plugin-log v0.8.0
- github.com/hashicorp/terraform-plugin-testing v1.2.0
+ github.com/hashicorp/terraform-plugin-docs v0.15.0
+ github.com/hashicorp/terraform-plugin-framework v1.3.1
+ github.com/hashicorp/terraform-plugin-go v0.16.0
+ github.com/hashicorp/terraform-plugin-log v0.9.0
+ github.com/hashicorp/terraform-plugin-testing v1.3.0
) I attach a png and a flamegrah (flamegraph in gist cpu.svg) |
A profiling result for a complete call of |
A profiling result for a complete call of |
Hi @jeremmfr 👋 Would you be able to try out hashicorp/terraform-plugin-go#308? From my local testing with the hashicups-pf example, it reduced the plan time by over half. I'm curious what level of real world benefit you might see as well. |
Hi @bflad 👋 We launch multiple scenarios to compare potential benefit. The PR reduce time but there is always a gap between SDKv2 and framework version of provider. The result:
The difference between Terraform code
resource "hashicups_order" "example" {
dynamic "items" {
for_each = range(1, 1000)
content {
quantity = items.value
}
}
}
resource "junos_security_address_book" "global" {
name = "global"
dynamic "network_address" {
for_each = range(1, 1000)
content {
name = "test${network_address.value}"
value = "1.1.1.1/32"
}
}
}
resource "junos_security_address_book" "global" {
name = "global"
dynamic "address_set" {
for_each = range(1, 1000)
content {
name = "test${address_set.value}"
address = ["baz"]
}
}
} Go replacein go.mod to use PR terraform-plugin-go#308 replace github.com/hashicorp/terraform-plugin-go => github.com/hashicorp/terraform-plugin-go v0.17.1-0.20230630191346-2155f0b1810f I run new profiling with pprof in last scenario ( The result in png and flamegraph (in gist) |
Thanks for the confirmation and the additional context, @jeremmfr. 😄 Given the overall very positive effects, I've pulled in the upstream changes and will cut a release of those shortly. I'm guessing there are two threads to pull on next with the framework side of things:
One other reality is that the framework went GA with its data handling half in terraform-plugin-go and half in terraform-plugin-framework. There is a lot of passing back and forth between the type systems in the |
…rmValue() Reference: #775 The prior implementation used the exported `AttributeTypes()` method, which in this case was unnecessarily creating a copy of the map when it was only be used for walking the existing data. At scale, such as handling 1000+ objects, this creates unnecessary pressure on the Go garbage collector. `benchstat` comparison with new benchmark test: ```text goos: darwin goarch: arm64 pkg: github.com/hashicorp/terraform-plugin-framework/types/basetypes │ original │ proposed │ │ sec/op │ sec/op vs base │ ObjectValueToTerraformValue1000-10 408.4µ ± 1% 318.4µ ± 1% -22.02% (p=0.000 n=10) │ original │ proposed │ │ B/op │ B/op vs base │ ObjectValueToTerraformValue1000-10 449.2Ki ± 0% 286.6Ki ± 0% -36.19% (p=0.000 n=10) │ original │ proposed │ │ allocs/op │ allocs/op vs base │ ObjectValueToTerraformValue1000-10 2.051k ± 0% 2.020k ± 0% -1.51% (p=0.000 n=10) ```
…rmValue() (#791) Reference: #775 The prior implementation used the exported `AttributeTypes()` method, which in this case was unnecessarily creating a copy of the map when it was only be used for walking the existing data. At scale, such as handling 1000+ objects, this creates unnecessary pressure on the Go garbage collector. `benchstat` comparison with new benchmark test: ```text goos: darwin goarch: arm64 pkg: github.com/hashicorp/terraform-plugin-framework/types/basetypes │ original │ proposed │ │ sec/op │ sec/op vs base │ ObjectValueToTerraformValue1000-10 408.4µ ± 1% 318.4µ ± 1% -22.02% (p=0.000 n=10) │ original │ proposed │ │ B/op │ B/op vs base │ ObjectValueToTerraformValue1000-10 449.2Ki ± 0% 286.6Ki ± 0% -36.19% (p=0.000 n=10) │ original │ proposed │ │ allocs/op │ allocs/op vs base │ ObjectValueToTerraformValue1000-10 2.051k ± 0% 2.020k ± 0% -1.51% (p=0.000 n=10) ```
@bflad Any update on this issue? Or any suggestion on workaround? |
Module version
Description
After migrating resources of my provider jeremmfr/junos from SDK plugin to this framework plugin, the time to run a
terraform plan
with a config that have many block sets has been increased very significantly.For 1000 items of block set, a
terraform plan
(with empty state) with provider including modulesdk/v2
take ~1.3 seconds and take ~ 70 seconds with provider includingplugin-framework
.A user of my provider has a time of 19 minutes to run terraform plan with the new version of the provider including
plugin-framework
instead of 52 seconds with the previous version of the provider including modulesdk/v2
Tests
I tested to remove all
PlanModifiers
andValidators
fields on each attribute, andValidateConfig
function for resources, using the latest version of this module (v1.3.1) but there's no change.The problem disappears if replace
schema.SetNestedBlock
withschema.ListNestedBlock
: 70 seconds to 1 second.I reproduce the problem with provider
hashicups
andhashicups_order
resources.I tested 1000 blocks
items
on a resourcehashicups_order
with different modifications ofitems
block.hashicorp/terraform-provider-hashicups schema.TypeSet : 3.8 - 4 seconds
hashicorp/terraform-provider-hashicups schema.TypeList : 0.5 - 0.8 seconds
hashicorp/terraform-provider-hashicups-pf schema.SetNestedBlock : 49.1 - 49.7 seconds
hashicorp/terraform-provider-hashicups-pf schema.ListNestedBlock : 0.8 - 1.1 seconds
hashicorp/terraform-provider-hashicups-pf schema.SetNestedAttribute : 49.0 - 49.4 seconds
hashicorp/terraform-provider-hashicups-pf schema.ListNestedAttribute : 0.7 - 0.9 seconds
Relevant provider source code
To test with block sets, clone hashicorp/terraform-provider-hashicups-pf and apply this patch :
& disable
hashicups.NewClient
code in provider configure functionTo test with nested atttribute sets, clone hashicorp/terraform-provider-hashicups-pf and apply this patch :
& disable
hashicups.NewClient
code in provider configure functionTerraform Configuration Files
To test with block sets:
To test with nested attribute sets:
Expected Behavior
The
terraform plan
command takes a reasonable time to run when there are many block sets.Actual Behavior
The
terraform plan
command takes a very long time to run when there are many block sets.Steps to Reproduce
terraform init
terraform plan
References
jeremmfr/terraform-provider-junos#498
The text was updated successfully, but these errors were encountered: