-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
unique: large string still referenced, after interning only a small substring #69370
Comments
Related Issues and Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
As @Deleplace states, this is already fixed. The only question is whether or not to backport it. I'll come back with a decision today. |
Ah and, thank you @Deleplace for filing an issue. :) |
@gopherbot Please open backport to 1.23 Since the unique package is new in 1.23, we should implement this optimization there as well, for consistent behavior. |
Backport issue(s) opened: #69383 (for 1.23). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Thanks @ianlancetaylor! |
Change https://go.dev/cl/612295 mentions this issue: |
Currently the unique package tries to clone strings that get stored in its internal map to avoid retaining large strings. However, this falls over entirely due to the fact that the original string is *still* stored in the map as a key. Whoops. Fix this by storing the cloned value in the map instead. This change also adds a test which fails without this change. For #69370. Fixes #69383. Change-Id: I1a6bb68ed79b869ea12ab6be061a5ae4b4377ddb Reviewed-on: https://go-review.googlesource.com/c/go/+/610738 Reviewed-by: Michael Pratt <[email protected]> Auto-Submit: Michael Knyszek <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit 21ac23a) Reviewed-on: https://go-review.googlesource.com/c/go/+/612295 Auto-Submit: Tim King <[email protected]>
Go version
go version go1.23.1 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
book
(300MB)word
which is a small substring ofbook
, usingunique.Make
runtime.GC
, after the last use ofbook
, before the last use ofword
runtime.ReadMemStats
What did you see happen?
Program is still using 300MB
What did you expect to see?
Program should be using less than 10MB
Discussion
This issue has already been fixed by @mknyszek in CL 610738. The change will be included in the future Go 1.24.
The current issue is about documenting the behavior of Go 1.23.0 and Go 1.23.1 when interning strings, and retaining more memory than expected.
The problem arises only with strings, not with other types comparable with
==
. String is the only comparable type that supports slicing.When interning a small substring
y
of a large stringx
, 2 strategies are possible in the implementation ofunique.Make
:y
, withinx
.x
will not be garbage collected, because the object pool inunique
is keeping a reference to a part of it. The user is responsible about the memory consequences of interning a substring. The user may decide to callstrings.Clone
beforehand themself.y
into a fresh stringy2
, and interny2
.x
may then be garbage collected.unique
implements strategy (2).Before the fix 610738,
unique.Make
did proactively clone input strings. However, an internal map was still referencing the original input strings, which was unintended.(in this diagram,
Bwords
is a[]unique.Handle[string]
)After the fix 610738,
unique.Make
proactively clones input strings, and then keeps only references to the clones. The large original input strings are then properly garbage collected.The text was updated successfully, but these errors were encountered: