Skip to content
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

slices: low performance from common misuse of Delete #58818

Closed
earthboundkid opened this issue Mar 1, 2023 · 4 comments
Closed

slices: low performance from common misuse of Delete #58818

earthboundkid opened this issue Mar 1, 2023 · 4 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@earthboundkid
Copy link
Contributor

Problem:

A quick search for slices.Delete on SourceGraph shows that many calls to slices.Delete are preceded by a call to slices.Index. This is often done in a loop, leading to needlessly terrible performance.

Possible solutions:

  • Remove Delete from the standard library slices package.
  • Accept and add slices: add DeleteFunc #54768 before slices is added to the standard library.
@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 1, 2023
@dmitshur dmitshur added this to the Backlog milestone Mar 1, 2023
@dmitshur
Copy link
Contributor

dmitshur commented Mar 1, 2023

CC @ianlancetaylor, @eliben.

@ianlancetaylor
Copy link
Contributor

Can you link to a couple of places? Thanks.

I'm fine with adding DeleteFunc but I don't see how it makes sense to remove Delete. The function's doc comment is even careful to explain its performance.

@earthboundkid
Copy link
Contributor Author

https://sourcegraph.com/search?q=context:global+slices.Delete+lang:go+&patternType=standard&sm=1&groupBy=repo

I'm just going to do cursory reviews of the first handful of examples:

  • pkg/bgpv1/gobgp/reconcile.go Has comment "Loop over announcements in reverse order so we can delete entries without effecting iteration." This is inefficient because it repeatedly moves tail elements in the case where there are many elements to delete.
  • pkg/bgpv1/gobgp/routermgr.go Does the same thing
  • operator/pkg/lbipam/lbipam.go Does the same thing
  • operator/pkg/lbipam/range_store.go Unclear from context if this is problematic. Might be okay.
  • tools/utils/misc.go Has "RemoveAll" utility which loops through with Delete.
  • There are some false positive string matches in Kubernetes
  • internal/service/emr/cluster.go Not totally clear how it's being used, but it's in a double nested loop, which is a bad sign to begin with.
  • internal/filtering/rewrite/storage.go False positive string match
  • vendor/github.com/jesseduffield/generics/slices/slices.go Okay. Just a utility to pass i and i+1 to slices.Remove.
  • internal/types/document.go Okay
  • service/worker/scheduler/workflow.go Okay
  • vendor/github.com/jesseduffield/generics/slices/delegated_slices.go Just a wrapper function.
  • vendor/github.com/containers/image/v5/manifest/docker_schema1.go "backwards loop so that we keep the remaining indexes after removing items"
  • tools/cmd/unicode_input/main.go Okay
  • modules/distributor/forwarder/manager_test.go Doesn't seem to do any work slices.Delete(o.tenantIDToForwarders["testTenantID"], idx, idx)
  • internal/service/elbv2/listener_test.go Okay
  • internal/service/elbv2/listener_rule_test.go Okay
  • pkg/plugins/runtime/k8s/controllers/cni_taint_controller.go Unclear from context. Probably okay.
  • exp/orderbook/edges.go Okay
  • cmd/gitserver/server/vcs_packages_syncer_test.go In a loop. Would be better served by slices.DeleteFunc.
  • vendor/github.com/containers/image/v5/manifest/docker_schema1.go Repeat. Bad.
  • detector.go In a loop. Looks bad.
  • gi/winlists.go Okay
  • core/internal/testutils/evmtest/evmtest.go Seems okay
  • internal/cmd/ssh.go In a loop. Seems bad.

Around a quarter of examples seem to be misuses, and many examples are some variant of i := slices.Index(s, something); if i != -1 { s = slices.Delete(s, i, i+1) }.

@seankhliao seankhliao changed the title slices: Delete is an attractive nuisance slices: low performance from common misuse of Delete Mar 3, 2023
@rsc
Copy link
Contributor

rsc commented Mar 8, 2023

Closing as duplicate of #54768.

@rsc rsc closed this as completed Mar 8, 2023
@golang golang locked and limited conversation to collaborators Mar 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants