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

High CPU usage for _reaper #44

Closed
vincentbernat opened this issue Jul 16, 2021 · 2 comments
Closed

High CPU usage for _reaper #44

vincentbernat opened this issue Jul 16, 2021 · 2 comments

Comments

@vincentbernat
Copy link
Contributor

Hey!

After profiling a program, I have noticed that the _reaper function is called very often and responsible for some quite CPU usage due to this. From my understanding, it is running at each tick as long as there is a DBus related task running, which is always if you are listening for signals.

I would suggest to just sleep a bit inside reaper.

  5002518   18.592    0.000  752.277    0.000 base_events.py:1815(_run_once)
  5002518    5.646    0.000  681.874    0.000 selectors.py:452(select)
  5002518  673.818    0.000  673.818    0.000 {method 'poll' of 'select.epoll' objects}
  5007678    3.841    0.000   45.105    0.000 events.py:78(_run)
  5007678    2.863    0.000   41.264    0.000 {method 'run' of 'Context' objects}
  5000867   11.825    0.000   34.350    0.000 dbussy.py:1454(_reaper)
  5003419    4.501    0.000   20.014    0.000 base_events.py:736(call_soon)
  5003419    5.591    0.000   14.493    0.000 base_events.py:765(_call_soon)
  5007620    5.966    0.000    8.111    0.000 events.py:31(__init__)
@vincentbernat
Copy link
Contributor Author

Just switching from call_soon(...) to call_later(0.1, ...) fixes the issue. However, I am wondering if you could not just append a callback to the scheduled tasks to run or signal the reaper instead of having an active event loop?

@ldo
Copy link
Owner

ldo commented Jul 16, 2021

The whole reason the TaskKeeper/_reaper mechanism exists is because asyncio does not keep strong refs to the task objects it creates. So they are liable to disappear at unexpected times before they complete. So the TaskKeeper base class keeps strong refs to created tasks, and the _reaper callback exists to watch for completed tasks, to get rid of the unneeded task objects.

Yeah, I should probably throttle the frequency at which the _reaper task runs. Maybe even an interval of 0.25 seconds or a second should be sufficient. Or make it caller-configurable.

Either that, or come up with a more elegant mechanism.

vincentbernat added a commit to vincentbernat/dbussy that referenced this issue Jul 16, 2021
asyncio is only maintaining weak references to task. To avoid them
being destroyed while still pending, we need to keep a reference on
them. Previously, a function was scheduled at each tick to cleanup
done tasks. Instead, we add a callback to the task to cleanup its own
reference when done.

Fix ldo#44.
@ldo ldo closed this as completed in e9929f4 Jul 17, 2021
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 a pull request may close this issue.

2 participants