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

feat(console): add warning for tasks that never yield #439

Merged
merged 17 commits into from Sep 14, 2023

Conversation

jefftt
Copy link
Contributor

@jefftt jefftt commented Jun 22, 2023

This PR only addresses the never yielding part of #203 wasn't sure if the hasn't yielded in a long time part should be in the same warning or not.

@jefftt jefftt requested a review from a team as a code owner June 22, 2023 00:07
Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

Thanks for your PR!

I agree with the approach to splitting #203 into 2 separate lints. One for tasks that have never yielded (this PR) and another for tasks that have long poll times (but have yielded at least once). That's a good idea!

I've got a few suggestions for changes here. Would you be able to have a look at them?

tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
console-subscriber/examples/busy_loop.rs Outdated Show resolved Hide resolved
tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
@jefftt
Copy link
Contributor Author

jefftt commented Jul 12, 2023

Thanks for the helpful review! Changes have been applied

@jefftt jefftt requested review from hds and hawkw July 12, 2023 13:44
Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

Thanks for the changes!

I tested this locally and found an issue. The lint isn't always being run at the right time to catch the "never yielded" state. This is because lints only get run when a task receives an update.

See this video of my test:

Screen.Recording.2023-07-12.at.16.56.21.mov

The first time you start tokio-console (using the app example), the lint will be run (because all tasks are received and this counts as an update). Since 1 second has probably already passed,check() will return true and we see the warning.

However, when the greedy task gets spawned again (which is what would happen if a task gets spawned after tokio-console has already started running), it only gets checked on a state transition. So you would see a check when it transitions to Running and another when it transitions to state Completed. Since there are no further updates for this task, the lint will never be run again. And since it doesn't yield, there won't be further updates - that is of course the whole point of the lint! (-;

Have a look at the tracing events I produced from within the NeverYielded::check method:

2023-07-12T14:45:02.401182Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Running, total_polls: 1, busy: 9.778227771s
2023-07-12T14:45:02.626523Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Running, total_polls: 1, busy: 10.003567771s
2023-07-12T14:45:13.625785Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Running, total_polls: 1, busy: 998.316004ms
2023-07-12T14:45:13.626350Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Completed, total_polls: 1, busy: 20.003362491s
2023-07-12T14:45:33.625470Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Running, total_polls: 1, busy: 995.971509ms
2023-07-12T14:45:33.625605Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Completed, total_polls: 1, busy: 20.001640062s
2023-07-12T14:45:53.625837Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Running, total_polls: 1, busy: 991.334708ms
2023-07-12T14:45:53.626094Z  INFO tokio_console::warnings: checking for NeverYielded: 'Some("greedy")' state: Completed, total_polls: 1, busy: 20.004502567s

See how the first check happens when the task has already been running for 9 seconds. Then the subsequent checks (when the task is in state Running) occur when the task has been running for just under a second, so the warning check returns false.

If we got a bit luckier, that check might have happened 10 milliseconds later and it would have returned true. However, we probably need to find a better solution than being lucky.

It may be necessary for a lint to indicate that it should be checked again after some interval. This would allow the NeverYielded lint to ask to be checked again, for a specific task, at some time after the 1 second would have passed (or a different period if we make that default value configurable).

The TasksState::update_tasks() would then need a way to keep track of which lints need to be rechecked and then recheck them during the next cycle, even if the task itself hasn't been updated.

Sorry for the big dump of information. If you're still interested in working on this topic and need some help, let me know. You can comment here in the PR, or if you're on Discord, you can find me in the Tokio server as haydenstainsby (just post in the #console channel, I'll see it).

@jefftt
Copy link
Contributor Author

jefftt commented Jul 20, 2023

ah i see yeah that makes sense thank you for the detailed explaination. would still be interested in working on this - just need to find the time :) happy to pass this off if someone else gets to it before me but will take a stab otherwise

@jefftt
Copy link
Contributor Author

jefftt commented Aug 12, 2023

@hds finally got around to this and found an easy change to make to fix this issue which is to lint every task on each update. not sure if the performance hit that it takes is worth it though. thoughts?

@hds
Copy link
Collaborator

hds commented Aug 13, 2023

@jefftt thanks for looking into this further! I just wanted to let you know that it will be a few days before I look at this PR as I'm on holiday at the moment. I should get to it in the middle of next week.

Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

Thanks for your work on this PR!

I think we need to find a more light weight solution. This approach will potentially add a lot of unnecessary computational overhead in every update cycle.

Would you like to discuss some different options?

tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
@jefftt
Copy link
Contributor Author

jefftt commented Sep 2, 2023

Thanks for your help, as discussed offline, I updated the PR with the suggestions

Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

Great work! I think that the logic here is almost completely fine (one case where I believe we may lint some tasks twice). I've also got some style suggestions which I think will help us reason about the flow more easily in the future.

tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
@jefftt jefftt requested a review from hds September 12, 2023 14:59
@hds
Copy link
Collaborator

hds commented Sep 13, 2023

@jefftt Thanks for your changes! I was hoping to get to this review today, but it might be tomorrow. Just wanted to let you know that it will be soon!

Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

Thanks for your changes, we're almost there!

The debug assert in Linter<T>::format is currently causing tokio-console to panic when viewing the details for a task with a warning. Looks like it's just a logic flip.

I've also got some last style nits.

tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
tokio-console/src/warnings.rs Outdated Show resolved Hide resolved
tokio-console/src/state/tasks.rs Outdated Show resolved Hide resolved
jefftt and others added 4 commits September 14, 2023 08:28
Co-authored-by: Hayden Stainsby <hds@caffeineconcepts.com>
Co-authored-by: Hayden Stainsby <hds@caffeineconcepts.com>
Co-authored-by: Hayden Stainsby <hds@caffeineconcepts.com>
Co-authored-by: Hayden Stainsby <hds@caffeineconcepts.com>
@jefftt jefftt requested a review from hds September 14, 2023 12:33
Copy link
Collaborator

@hds hds left a comment

Choose a reason for hiding this comment

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

This looks all set now. Thanks for all the work that you put into this PR, we really appreciate it!

Congratulations on your first tokio-console contribution!

@hds hds merged commit bc81b8a into tokio-rs:main Sep 14, 2023
12 checks passed
hawkw pushed a commit that referenced this pull request Sep 29, 2023
feat(console): add warning for tasks that never yield (#439)

Adds a new warning for tasks that have never yielded.

This is more complicated than it sounds, because under the previous
behavior, tasks are only linted when they are created or updated. A task
that never yields doesn't get updated, so if it gets linted before the
"never yielded" threshold is reached (defaults to 1 second), the warning
returns false and the task won't get linted again.

To solve this problem, warnings can now return a response that requests
to be rechecked later. In practice, this later is on the next update
cycle, at which point the task may again request to be rechecked later.

For this warning, the overhead will likely be only a single recheck
after task creation (and the fact that we need to store those task IDs
between updates). We will have to consider the performance impact of any
new warnings which may request rechecks as they are added.

Co-authored-by: Hayden Stainsby <hds@caffeineconcepts.com>
hawkw added a commit that referenced this pull request Sep 29, 2023
# Changelog

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## console-subscriber-v0.2.0 - (2023-09-29)

[0b0c1af](https://github.com/tokio-rs/console/commit/0b0c1aff18c3260d3a45a78f6c0d6f4206af1cbb)...[0b0c1af](https://github.com/tokio-rs/console/commit/0b0c1aff18c3260d3a45a78f6c0d6f4206af1cbb)

### <a id = "console-subscriber-v0.2.0-breaking"></a>Breaking Changes
- **Update Tonic and Prost dependencies ([#364](#364 ([f9b8e03](https://github.com/tokio-rs/console/commit/f9b8e03bd7ee1d0edb441c94a93a350d5b06ed3b))<br />This commit updates the public dependencies `prost` and `tonic` to
semver-incompatible versions (v0.11.0 and v0.8.0, respectively). This is
a breaking change for users who are integrating the `console-api` protos
with their own `tonic` servers or clients.
- **Update `tonic` to v0.10 and increase MSRV to 1.64 ([#464](#464 ([96e62c8](https://github.com/tokio-rs/console/commit/96e62c83ef959569bb062dc8fee98fa2b2461e8d))<br />This is a breaking change for users of `console-api` and
`console-subscriber`, as it changes the public `tonic` dependency to a
semver-incompatible version. This breaks compatibility with `tonic`
0.9.x and `prost` 0.11.x.

### Added

- [**breaking**](#console-subscriber-v0.2.0-breaking) Update Tonic and Prost dependencies ([#364](#364)) ([f9b8e03](f9b8e03))
- Add support for Unix domain sockets ([#388](#388)) ([a944dbc](a944dbc), closes [#296](#296))
- Add scheduled time per task ([#406](#406)) ([f280df9](f280df9))
- Add task scheduled times histogram ([#409](#409)) ([d92a399](d92a399))
- Update `tonic` to 0.9 ([#420](#420)) ([48af1ee](48af1ee))
- Update MSRV to Rust 1.60.0 ([b18ee47](b18ee47))
- Expose server parts ([#451](#451)) ([e51ac5a](e51ac5a))
- Add cfg `console_without_tokio_unstable` ([#446](#446)) ([7ed6673](7ed6673))
- Add warning for tasks that never yield ([#439](#439)) ([d05fa9e](d05fa9e))
- [**breaking**](#console-subscriber-v0.2.0-breaking) Update `tonic` to v0.10 and increase MSRV to 1.64 ([#464](#464)) ([96e62c8](96e62c8))

### Documented

- Fix unclosed code block ([#463](#463)) ([362bdbe](362bdbe))
- Update MSRV version docs to 1.64 ([#467](#467)) ([94a5a51](94a5a51))

### Fixed

- Fix build on tokio 1.21.0 ([#374](#374)) ([c34ac2d](c34ac2d))
- Fix off-by-one indexing for `callsites` ([#391](#391)) ([43891ab](43891ab))
- Bump minimum Tokio version ([#397](#397)) ([bbb8f25](bbb8f25), fixes [#386](#386))
- Fix self wakes count ([#430](#430)) ([d308935](d308935))
- Remove clock skew warning in `start_poll` ([#434](#434)) ([4a88b28](4a88b28))
- Do not report excessive polling ([#378](#378)) ([#440](#440)) ([8b483bf](8b483bf), closes [#378](#378))
- Correct retain logic ([#447](#447)) ([36ffc51](36ffc51))

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
hawkw added a commit that referenced this pull request Sep 29, 2023
# Changelog

All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## tokio-console-v0.1.10 - (2023-09-29)

[7d009f8](https://github.com/tokio-rs/console/commit/7d009f87120ce0c89f5f9c5311f05b6756ca770f)...[7d009f8](https://github.com/tokio-rs/console/commit/7d009f87120ce0c89f5f9c5311f05b6756ca770f)

### <a id = "tokio-console-v0.1.10-breaking"></a>Breaking Changes
- **Update Tonic and Prost dependencies ([#364](#364 ([f9b8e03](https://github.com/tokio-rs/console/commit/f9b8e03bd7ee1d0edb441c94a93a350d5b06ed3b))<br />This commit updates the public dependencies `prost` and `tonic` to
semver-incompatible versions (v0.11.0 and v0.8.0, respectively). This is
a breaking change for users who are integrating the `console-api` protos
with their own `tonic` servers or clients.
- **Update `tonic` to v0.10 and increase MSRV to 1.64 ([#464](#464 ([96e62c8](https://github.com/tokio-rs/console/commit/96e62c83ef959569bb062dc8fee98fa2b2461e8d))<br />This is a breaking change for users of `console-api` and
`console-subscriber`, as it changes the public `tonic` dependency to a
semver-incompatible version. This breaks compatibility with `tonic`
0.9.x and `prost` 0.11.x.

### Added

- [**breaking**](#tokio-console-v0.1.10-breaking) Update Tonic and Prost dependencies ([#364](#364)) ([f9b8e03](f9b8e03))
- Only suggest opening issues for panics ([#365](#365)) ([da2a89c](da2a89c))
- Init error handling before subcmds ([#365](#365)) ([ec66eda](ec66eda))
- Filter out boring frames in backtraces ([#365](#365)) ([95a5e54](95a5e54))
- Include config options in autogenerated issues ([#365](#365)) ([3244a1f](3244a1f))
- Reduce decimal digits in UI ([#402](#402)) ([c13085e](c13085e))
- Use tokio task ids in task views ([#403](#403)) ([f5b06d2](f5b06d2))
- Add support for Unix domain sockets ([#388](#388)) ([a944dbc](a944dbc), closes [#296](#296))
- Add scheduled time per task ([#406](#406)) ([f280df9](f280df9))
- Add task scheduled times histogram ([#409](#409)) ([d92a399](d92a399))
- Update `tonic` to 0.9 ([#420](#420)) ([48af1ee](48af1ee))
- Update MSRV to Rust 1.60.0 ([b18ee47](b18ee47))
- Migrate to `ratatui` and update `crossterm` ([#425](#425)) ([b209dd6](b209dd6))
- Help view modal ([#432](#432)) ([359a4e7](359a4e7))
- Add way to inspect details of task from resource view ([#449](#449)) ([132ed4e](132ed4e), closes [#448](#448))
- Add warning for tasks that never yield ([#439](#439)) ([d05fa9e](d05fa9e))
- [**breaking**](#tokio-console-v0.1.10-breaking) Update `tonic` to v0.10 and increase MSRV to 1.64 ([#464](#464)) ([96e62c8](96e62c8))

### Documented

- Update screenshots in README ([#419](#419)) ([e9bcd67](e9bcd67))
- Revert "update screenshots in README ([#419](#419))" ([993a3d9](993a3d9))
- Update screenshots in README ([#421](#421)) ([8a27f96](8a27f96))
- Add column descriptions for all tables ([#431](#431)) ([e3cf82b](e3cf82b))
- Update MSRV version docs to 1.64 ([#467](#467)) ([94a5a51](94a5a51))

### Fixed

- Fix ascii-only flipped input ([#377](#377)) ([652ac34](652ac34))
- Declare `tokio-console` bin as `default-run` ([#379](#379)) ([9ce60ec](9ce60ec))
- Make `retain_for` default to 6s if not specfied ([#383](#383)) ([0a6012b](0a6012b), fixes [#382](#382))
- Enable view-switching keystrokes on details views ([#387](#387)) ([f417d7a](f417d7a))
- Fix `ViewOptions` default lang' ([#394](#394)) ([a1cf1b8](a1cf1b8), fixes [#393](#393))
- Remove `tracing-subscriber` 0.2 from dependencies ([#404](#404)) ([768534a](768534a))
- Fix calculation of busy time during poll ([#405](#405)) ([e2c536a](e2c536a))
- Remove histogram minimum count ([#424](#424)) ([02cf8a6](02cf8a6))
- Remove trailing space from task/resource location ([#443](#443)) ([90e5918](90e5918))
- Make long locations readable ([#441](#441)) ([9428d7f](9428d7f), closes [#411](#411))
- Fix task detail view Id to display remote tokio::task::Id ([#455](#455)) ([70c3952](70c3952))

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
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.

None yet

3 participants