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

timeutil: stack-allocate Timer, remove pooling #119901

Merged

Conversation

nvanbenschoten
Copy link
Member

Informs #119593.
Closes #38055.

This PR removes the pooling of timeutil.Timer structs and, in doing so, permits the structs to be stack allocated so that no pooling is necessary. This superfluous (and in hindsight, harmful) memory pooling was introduced in f11ec1c, which also added very necessary pooling for the internal time.Timer structs.

The pooling was harmful because it mandated a contract where Timer structs could not be used after their Stop method was called. This was surprising (time.Timer has no such limitation) and led to subtle use-after-free bugs over time (#61373 and #119595). It was also unnecessary because the outer Timer structs can be stack allocated. Ironically, the only thing that causes them to escape to the heap was the pooling mechanism itself. Removing pooling solves the issue.

name      old time/op    new time/op    delta
Timer-10     153µs ± 1%     152µs ± 1%   ~     (p=0.589 n=10+9)

name      old alloc/op   new alloc/op   delta
Timer-10      200B ± 0%      200B ± 0%   ~     (all equal)

name      old allocs/op  new allocs/op  delta
Timer-10      3.00 ± 0%      3.00 ± 0%   ~     (all equal)

The PR then improves the memory pooling of the inner time.Timer so that it is always recycled. This was originally identified by @andreimatei in #13466 (review).

Doing so has a positive impact on the microbenchmark introduced in the first commit, demonstrating that timers can be stack-allocated and require zero heap allocations:

name      old time/op    new time/op    delta
Timer-10     152µs ± 1%     153µs ± 1%      ~     (p=0.133 n=9+10)

name      old alloc/op   new alloc/op   delta
Timer-10      200B ± 0%        0B       -100.00%  (p=0.000 n=10+10)

name      old allocs/op  new allocs/op  delta
Timer-10      3.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)

cc. @andreimatei @ajwerner

Epic: None
Release note: None

@nvanbenschoten nvanbenschoten requested review from yuzefovich and a team March 5, 2024 04:38
@nvanbenschoten nvanbenschoten requested review from a team as code owners March 5, 2024 04:38
@nvanbenschoten nvanbenschoten requested a review from a team March 5, 2024 04:38
@nvanbenschoten nvanbenschoten requested review from a team as code owners March 5, 2024 04:38
@nvanbenschoten nvanbenschoten requested review from xinhaoz, msbutler, herkolategan and renatolabs and removed request for a team March 5, 2024 04:38
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@nvanbenschoten nvanbenschoten force-pushed the nvanbenschoten/remTimerPool branch from cebe308 to 48341c7 Compare March 5, 2024 05:39
Copy link
Collaborator

@mgartner mgartner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm: Nice!

Reviewed 1 of 1 files at r1, 47 of 47 files at r2, 2 of 2 files at r3, all commit messages.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @herkolategan, @msbutler, @renatolabs, @xinhaoz, and @yuzefovich)

Copy link
Member

@dt dt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

@dt dt removed the request for review from msbutler March 5, 2024 15:44
Copy link
Member

@yuzefovich yuzefovich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks! :lgtm:

Reviewed 1 of 1 files at r1, 47 of 47 files at r2, 2 of 2 files at r3, all commit messages.
Reviewable status: :shipit: complete! 2 of 0 LGTMs obtained (waiting on @herkolategan, @renatolabs, and @xinhaoz)

@nvanbenschoten nvanbenschoten force-pushed the nvanbenschoten/remTimerPool branch 2 times, most recently from e2f61b6 to 7e82b7f Compare March 5, 2024 20:27
This commit adds a new benchmark for timeutil.Timer creation and use.

```
name      time/op
Timer-10  153µs ± 1%

name      alloc/op
Timer-10   200B ± 0%

name      allocs/op
Timer-10   3.00 ± 0%
```

Epic: None
Release note: None
Informs cockroachdb#119593.
Closes cockroachdb#38055.

This commit removes the pooling of timeutil.Timer structs and, in doing so,
permits the structs to be stack allocated so that no pooling is necessary. This
superfluous (and in hindsight, harmful) memory pooling was introduced in
f11ec1c, which also added very necessary pooling for the internal time.Timer
structs.

The pooling was harmful because it mandated a contract where Timer structs could
not be used after their Stop method was called. This was surprising (time.Timer
has no such limitation) and led to subtle use-after-free bugs over time (cockroachdb#61373
and cockroachdb#119595). It was also unnecessary because the outer Timer structs can be
stack allocated. Ironically, the only thing that causes them to escape to the
heap was the pooling mechanism itself. Removing pooling solves the issue.

```
name      old time/op    new time/op    delta
Timer-10     153µs ± 1%     152µs ± 1%   ~     (p=0.589 n=10+9)

name      old alloc/op   new alloc/op   delta
Timer-10      200B ± 0%      200B ± 0%   ~     (all equal)

name      old allocs/op  new allocs/op  delta
Timer-10      3.00 ± 0%      3.00 ± 0%   ~     (all equal)
```

Epic: None
Release note: None
This commit eliminates a case where a Timer's inner timer is not recycled. This
was originally identified by @andreimatei in cockroachdb#13466 (review).

```
name      old time/op    new time/op    delta
Timer-10     152µs ± 1%     153µs ± 1%      ~     (p=0.133 n=9+10)

name      old alloc/op   new alloc/op   delta
Timer-10      200B ± 0%        0B       -100.00%  (p=0.000 n=10+10)

name      old allocs/op  new allocs/op  delta
Timer-10      3.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
```

Epic: None
Release note: None
@nvanbenschoten nvanbenschoten force-pushed the nvanbenschoten/remTimerPool branch from 7e82b7f to 46a36e3 Compare March 5, 2024 20:44
@nvanbenschoten
Copy link
Member Author

TFTRs!

bors r+

@craig
Copy link
Contributor

craig bot commented Mar 6, 2024

This PR was included in a batch that timed out, it will be automatically retried

@craig
Copy link
Contributor

craig bot commented Mar 6, 2024

Build succeeded:

@craig craig bot merged commit d400c11 into cockroachdb:master Mar 6, 2024
18 checks passed
@nvanbenschoten nvanbenschoten deleted the nvanbenschoten/remTimerPool branch April 1, 2024 22:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants