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

Taskwarrior-tui uses a lot of CPU time when idle. #122

Closed
desbma opened this issue Feb 28, 2021 · 11 comments
Closed

Taskwarrior-tui uses a lot of CPU time when idle. #122

desbma opened this issue Feb 28, 2021 · 11 comments
Labels
bug Something isn't working

Comments

@desbma
Copy link
Contributor

desbma commented Feb 28, 2021

taskwarrior-tui uses a lot of CPU time when idle.

By a lot I don't mean 4 cores at 100%, but still a significant amount (some numbers below), which is not expected for a program completely idle.
I care because I typically have a terminal open with taskwarrior-tui always running, and for example I want to avoid draining my laptop battery.

$ taskwarrior-tui -V
taskwarrior-tui 0.10.4

$ time timeout 1 taskwarrior-tui
timeout 1 taskwarrior-tui  0,46s user 0,12s system 57% cpu 1,003 total

$ time timeout 60 taskwarrior-tui
timeout 60 taskwarrior-tui  24,26s user 3,67s system 46% cpu 1:00,00 total

Here we have measured an approximation of the CPU consumed on startup, and when taskwarrior is idle for 60s (no keyboard interaction).
During 1 minute of runtime, we have consumed about 27.5s of CPU time, close to 50% CPU utilization of a single core, which is huge for a program doing mostly nothing.

Possible ideas to improve CPU usage (I have only looked very briefly at the code):

  • Reduce the UI tick rate (currently 250ms)
  • Implement some caching in TTApp::update to reduce the number of task invocations when nothing has changed. For example if ~/.taskrc has not changed, there is not need to query the columns for the next report everytime.

@kdheepak If you agree I can help contribute some code for the second point.

@desbma desbma added the bug Something isn't working label Feb 28, 2021
@kdheepak
Copy link
Owner

kdheepak commented Feb 28, 2021

Thanks for reporting @desbma. I'm aware of this issue. It is related to this issue: #46

I believe the issue isn't the UI tick rate, but it is the polling for keyboard input in the background thread, which is currently between 5ms to 10ms. If you change these lines to 250ms your CPU consumption is going to decrease. You can try to build from source to test this:

let timeout = Duration::from_millis(10)
.checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_millis(5));

However increasing the tick rate causes the race condition described the issue in #46.

In this comment on that thread, I describe exactly what I think is going on: #46 (comment)

This comment is where @donbex tested it with the current timing for the polling: #46 (comment)

I'd happily accept PRs or changes or even just suggestions on how to solve it. I'm open to using any paradigm (e.g. async polling) to solve this. This issue only occurs on alacritty with vi, vim and nvim.

Alternatively, I can make that a configuration option. If I do that, this problem will be much more easily resolved (albeit in a hacky way).

@desbma
Copy link
Contributor Author

desbma commented Feb 28, 2021

I tried changing as you suggested with this patch:

diff --git a/src/util.rs b/src/util.rs
index 9405fbd..db4738b 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -86,9 +86,9 @@ impl Events {
                         continue;
                     }

-                    let timeout = Duration::from_millis(10)
+                    let timeout = Duration::from_millis(250)
                         .checked_sub(last_tick.elapsed())
-                        .unwrap_or_else(|| Duration::from_millis(5));
+                        .unwrap_or_else(|| Duration::from_millis(250));

                     if event::poll(timeout).unwrap() {
                         if let event::Event::Key(key) = event::read().unwrap() {

then recompiling with cargo build --release, and the CPU usage is better but still abnormally high : ~25% average when idle for 60s.

@kdheepak
Copy link
Owner

kdheepak commented Feb 28, 2021

That's odd. I thought that'd be the issue. Can you try increasing the tick_rate duration here:

tick_rate: Duration::from_millis(250),

How many tasks do you have in your task list? I have about 30 or so tasks in my task list.

Screen Shot 2021-02-28 at 3 17 55 PM

This screenshot above is htop and taskwarrior-tui running in two different panes. The CPU usage of the taskwarrior-tui process is about 3.1%. At the top of the pane I have iTerm2 monitoring the CPU of the computer which is around 10%. I'm running the latest master with no changes for this screenshot.

@kdheepak
Copy link
Owner

That is not to say that there aren't memory / CPU performance issues that need to be taken care of here. I'm happy to include any patch that you think will improve performance. I'm just a little surprised that htop is not showing the performance you are seeing with time timeout taskwarrior-tui.

@kdheepak
Copy link
Owner

I'm also seeing similarly high numbers with time timeout taskwarrior-tui.

time timeout 10 ./target/release/taskwarrior-tui  1.59s user 1.38s system 29% cpu 10.012 total

Any idea why htop is not reporting similarly high numbers?

@desbma
Copy link
Contributor Author

desbma commented Feb 28, 2021

How many tasks do you have in your task list?

Around 100-150 depending on how you count.

The CPU usage of the taskwarrior-tui process is about 3.1%.

This is not measuring the overhead of all the short lived task subprocesses that are spawned. A simple task invocation makes 4500 system calls on my system. This quickly adds up when doing that several times per second when idle.

Changing the tick rate to 1s instead of 250ms as you last suggested improves the CPU usage as expected, but it's still about 10% of usage which is way too high for a program that is idle. It should be negligible (<1%).

I will see if I can work something out to improve it.

@cyrinux
Copy link

cyrinux commented Mar 1, 2021

Can we imagine a 1 minute tick auto refresh + a refresh on keypress and inotify events - write/update on the task database files?
For me too for the moment it consumes too much.

@kdheepak
Copy link
Owner

kdheepak commented Mar 1, 2021

In the latest master branch it does exactly that (thanks to @desbma)! 1 minute tick refresh with force updates on most key presses.

@cyrinux
Copy link

cyrinux commented Mar 1, 2021

In the latest master branch it does exactly that (thanks to @desbma)! 1 minute tick refresh with force updates on most key presses.

Ok nice, I realize I don't use the master on the computer where I spot it consume much. It is nice on the master. :-)

@desbma
Copy link
Contributor Author

desbma commented Mar 1, 2021

I'm closing this since the CPU usage is now reasonable for me.

@desbma desbma closed this as completed Mar 1, 2021
@kdheepak
Copy link
Owner

kdheepak commented Mar 1, 2021

I made a new release that addresses this issue: https://github.com/kdheepak/taskwarrior-tui/releases/tag/v0.11.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants