Skip to content

time: stop requiring Timer/Ticker.Stop for prompt GC #61542

Closed
@rsc

Description

@rsc

After almost a decade, I have finally implemented #8898, special-casing the channels used for timers (or maybe the timers used for channels) so that the timers are not in the timer heap when there are no channel operations pending on them. This means that the channels and timers can be GC'ed once they are no longer referenced, without having to wait for a timer to expire or explicitly Stop the timer. (By timer here I mean the data structure used by time.After, time.NewTimer, and time.NewTicker.)

This raises a question: do we want to guarantee that all future versions of Go will provide this behavior, so that code can rely on not needing to call the Stop methods? I think we probably should make that guarantee.

I propose we land my CL and document that After can be used without concern for GC and that NewTimer and NewTicker can be used without concern for deferring Stop just for GC. At the moment the doc comment for After describes the problem and basically says "don't use this function a lot". If we accept this proposal, we can remove that text. NewTimer and NewTicker do not mention needing to call Stop, although it is implied by After's doc comment. If we accept this proposal, we can document that Stop is not necessary for GC, so that people can stop calling Stop.

Activity

added this to the Proposal milestone on Jul 23, 2023
gopherbot

gopherbot commented on Jul 23, 2023

@gopherbot
Contributor

Change https://go.dev/cl/512355 mentions this issue: time: garbage collect unstopped Tickers and Timers

bcmills

bcmills commented on Jul 24, 2023

@bcmills
Contributor

This seems like it would require other Go implementations (such as gccgo and TinyGo) to implement those same special cases. Are we sure that's viable for them?

bcmills

bcmills commented on Jul 24, 2023

@bcmills
Contributor

That said, I think we basically have to do this to avoid the portability pitfall I mentioned in #8898 (comment). I don't want to be in a long-term state where it's ok to omit the Stop only if you know that your code will never be compiled with gccgo or TinyGo.

rsc

rsc commented on Jul 24, 2023

@rsc
ContributorAuthor

I can't see why it wouldn't be a viable change for gccgo or TinyGo. The change is not terribly complex: it just requires recognizing timers supporting channels and turning them on/off around blocking operations on those channels. See https://go.dev/cl/512355. Also, we have never held Go back before for secondary implementations to catch up, and I am reluctant to start doing that now.

In the second comment, I am not sure what "this" is in "basically have to do this".

bcmills

bcmills commented on Jul 24, 2023

@bcmills
Contributor

In the second comment, I am not sure what "this" is in "basically have to do this".

This proposal. That is: since the mainline implementation no longer requires a Stop, we need to require secondary implementations to provide the same behavior in order to avoid arguments about whether a given Stop is necessary (for portability) or redundant in code outside of the standard library.

rsc

rsc commented on Jul 24, 2023

@rsc
ContributorAuthor

I see. I completely agree that if the CL is submitted then we have to accept the proposal. This proposal is really "should we submit the CL?"

moved this to Incoming in Proposalson Jul 25, 2023
rsc

rsc commented on Jul 26, 2023

@rsc
ContributorAuthor

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

moved this from Incoming to Active in Proposalson Jul 26, 2023
ChrisHines

ChrisHines commented on Aug 1, 2023

@ChrisHines
Contributor

@rsc If I understand the implementation correctly a tight for-select loop including a timer channel will cause frequent resorting of timer heaps. Is that a performance concern? Has it been measured?

20 remaining items

modified the milestones: Proposal, Backlog on Aug 30, 2023
aykevl

aykevl commented on Sep 2, 2023

@aykevl

Finally got to this issue (holiday and all that).

So right now we use the standard library time package and implement the runtime side of it in our custom runtime. That implementation isn't great: it basically calls the provided function from inside the scheduler so any blocking call is probably going to mess things up. Consider it a work in progress.

Regarding the actual issue: it appears to require a bunch of special casing for timer channels. Maybe we'll implement that some day, but I can't promise that because it grows the runtime size even when timers aren't used and I very much would like to keep the runtime size as low as reasonably possible (while implementing the Go spec, of course).

(At the same time, the current design of the TinyGo runtime should garbage collect deadlocked goroutines as a side effect of how the scheduler works. I didn't actually test this though. AFAIK the main Go runtime doesn't do this. Just to show a different design results in different things being trivial or difficult).

added a commit that references this issue on Mar 13, 2024
508bb17
modified the milestones: Backlog, Go1.23 on May 23, 2024
locked and limited conversation to collaborators on May 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @rsc@aykevl@dgryski@ChrisHines@dmitshur

        Issue actions

          time: stop requiring Timer/Ticker.Stop for prompt GC · Issue #61542 · golang/go