hhd-dev / hhd

Handheld Daemon, a tool for configuring handheld devices.
GNU General Public License v3.0
76 stars 11 forks source link

[Feature Request] Auto-disable gyro when it is not used #63

Closed bakamomi closed 2 weeks ago

bakamomi commented 1 month ago

On GPD Win Max 2 (2003) setting Motion HZ to 1600 uses whopping 12% of one cpu core. Setting HZ to 50 reduces load to 2%, but it's still a lot.

Example output from systemd:

     Loaded: loaded (/etc/systemd/system/hhd_local@.service; enabled; preset: disabled)
     Active: active (running) since Thu 2024-05-02 23:01:23 UTC; 31s ago
   Main PID: 12976 (hhd)
      Tasks: 4 (limit: 57414)
     Memory: 38.0M
        CPU: 4.297s

In 30 seconds since the daemon launch, it already used 4 seconds of CPU time.

I don't know how it's implemented in HHD, but can you do something about this? Just a couple of ideas out of the top of my head:

  1. Rewrite polling in a lower-level language like C/Rust?
  2. Pause polling when gamepad isn't used. For example, poll just once in 2-3 seconds if standard xbox buttons haven't been used in a minute?
antheas commented 1 month ago

There is no measurable performance difference between 400hz and 1600hz, so 12% is not that big of an issue, the actuality is around 4-6% at 400hz, and if someone thinks that's too expensive, they can lower to 100hz which is also acceptable. When disabling gyro, utilization drops even further to .5% (controller still needs to output events, otherwise steam breaks).

Starting hhd takes around 2s of CPU time which could be better, but at the same time it is doing a lot of stuff, so you have to wait for utilization to stabilize first.

As for your points: 1) Most of the utilization, at least for devices that use the IIO subsystem such as yours, is due to the kernel. You can run the command time and see that system time accounts for around half of the CPU utilization. At most youre looking at halving the CPU usage, if you have a theoretical programming language that does not use CPU cycles. Handheld Daemon has been optimized aggressively and is faster than alternative compiled solutions.

At the end of the day, 1600hz is 1600 times you have to wake up the thread, sample the iio buffer, and write the events out, and those syscalls are where most of the cost is, not python.

2) I'm thinking of a good heuristic for disabling gyro, but it is on the backburner for now. I did add one for the touchpad.

As for how sampling is done, it is not done by Handheld Daemon. At startup, Handheld Daemon marshals the iio subsystem with either the appropriate interrupts (if your device has them) or the hrtimer kernel module. Then the kernel fills the buffer and wakes up hhd when there is a new sample, so it is not something that can be downregulated without disabling the buffer and restarting once gyro is needed.

At the end of the day, 4% of one core of a 8 core/16t machine is .3% CPU utilization, which translates to a transient rise in average PPT from 3.25-4.15W (at least on my device) to 4.25W when the device is completely idle, and which is completely washed out when a browser, a game, or steam are active.

Hopefully this answers your questions

bakamomi commented 1 month ago

4-6% might not be much for an application, but it's quite a lot for a daemon, which runs constantly (meaning, even when I'm not playing games and have no use for this daemon). In fact, in my testing hhd turned out to be the most resource-heavy daemon on my system. I simply opened htop and looked at the TIME+ column. HHD used twice as much CPU time as pipewire or opensnitch. It's roughly equal to kwin_wayland (a whole compositor).

If it's impossible to optimize, there should be a way to pause processing when the user isn't using gamepad.

Alternatively, would it be possible to make an alternative version of hhd that works like a launcher? So, the user would need to write hhd -- %command% so hhd would run only when a game is running? Kinda like mangohud/gamescope. In this case, 12% would be nothing.

antheas commented 1 month ago

You can always use the desktop version of the overlay to disable gyro or controller emulation when it is not needed. When you do that, the utilization will drop to 0. Or mouse mode, which also disables the controller emulation. I just have not found a way to do it automatically.

bakamomi commented 1 month ago

I guess the mouse mode is the fastest way to switch it on and off for now. But I hope you'll implement some automatic way to do it. If you don't mind I leave this report open to track when you implement this feature.

antheas commented 2 weeks ago

Added xbox elite controller emulation and rgb controls. Therefore, the only reason to use dualsense is for gyro and touchpad for steam input.

Gyro is autodisabled when using xbox style controllers.

In addition, double tapping the qam button will now open hhd in desktop mode (https://github.com/hhd-dev/hhd/commit/137e547c872d991499df6533759d9f38b73d88a6), so settings can be changed quickly.