Skip to content

timeutil: stack-allocate Timer, remove pooling#119901

Merged
craig[bot] merged 3 commits intocockroachdb:masterfrom
nvb:nvanbenschoten/remTimerPool
Mar 6, 2024
Merged

timeutil: stack-allocate Timer, remove pooling#119901
craig[bot] merged 3 commits intocockroachdb:masterfrom
nvb:nvanbenschoten/remTimerPool

Conversation

@nvb
Copy link
Copy Markdown
Contributor

@nvb nvb commented Mar 5, 2024

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

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

This change is Reviewable

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

@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
Copy Markdown
Contributor

@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
Copy Markdown
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)

@nvb nvb force-pushed the nvanbenschoten/remTimerPool branch 2 times, most recently from e2f61b6 to 7e82b7f Compare March 5, 2024 20:27
nvb added 3 commits March 5, 2024 15:43
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
@nvb nvb force-pushed the nvanbenschoten/remTimerPool branch from 7e82b7f to 46a36e3 Compare March 5, 2024 20:44
@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Mar 6, 2024

TFTRs!

bors r+

@craig
Copy link
Copy Markdown
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
Copy Markdown
Contributor

craig bot commented Mar 6, 2024

Build succeeded:

@craig craig bot merged commit d400c11 into cockroachdb:master Mar 6, 2024
@nvb nvb 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