Add dynamic SAV daemon - workload-dependent power saver adjustments#877
Add dynamic SAV daemon - workload-dependent power saver adjustments#877Mylinde wants to merge 4 commits intolinrunner:mainfrom
Conversation
Features: - Background daemon monitoring CPU load in battery mode - Dynamically adjusts platform profile, CPU energy policy, PCIE ASPM - Three workload states: low (<=30%), med (30-60%), high (>=60%) - Auto-detects available SAV profile from system capabilities - Hysteresis and minimum delay to prevent flapping Configuration: - SAV_DYNAMIC_ENABLE: Enable/disable feature (default: disabled) - SAV_DYNAMIC_INTERVAL: Sampling interval in seconds (default: 5) - SAV_DYNAMIC_SAMPLES: Moving average window size (default: 3) - SAV_DYNAMIC_THRESHOLDS: Low/high CPU % thresholds (default: 30,60) - SAV_DYNAMIC_HYSTERESIS: Hysteresis % (default: 5) - SAV_DYNAMIC_MIN_DELAY: Minimum delay between changes in seconds (default: 30) Integration: - Auto-starts with 'tlp init start' when enabled - Auto-stops with 'tlp init stop' - Includes full documentation in tlp.conf.in Complements platform-profile-autodetect (PR linrunner#875) for complete adaptive power management: 1. Auto-detect best available profiles 2. Dynamically adjust based on workload
|
To briefly illustrate how this works, here is a log output from being on SAV profile and using the platform_profile quiet. First, normal browsing, then compilation of the scx_scheduler p2dq and finally normal browsing again. |
Performance improvements: - Reduce CPU stat parsing from 4 awk calls to 1, using set and shell arithmetic - Optimize get_ac_power() to check only first battery (most systems have one) - Cache AC status, check only every 2*INTERVAL instead of every cycle (~80→3-4/hour) - Reduce logging I/O by only logging on state changes, not every cycle Reliability improvements: - Validate configured/auto-detected platform profile against system capabilities - Support dynamic profile selection (quiet, low-power, cool) based on hardware - Fix SAV profile preservation across state transitions (store original value) - Adjust hysteresis default from 5 to 3 for better med-zone coverage (34 vs 19%) Defaults: - SAV_DYNAMIC_HYSTERESIS: 5 → 3 (gives med state more room to trigger) - Low threshold: ≤33% | Med: 34-57% | High: ≥57% These optimizations maintain functionality while reducing daemon overhead, improving workload detection accuracy, and ensuring robust operation across different hardware configurations.
…daemon Performance improvements: - Implement adaptive interval sampling based on load trend - Stable load: 5-7s intervals (minimal overhead) - Rising load (>5%): 3s intervals (responsive) - Sharp rise (>10%): 2s intervals (very responsive) - Falling load: 7s intervals (conservative) - Add predictive threshold detection - When load approaches high threshold (±15%) while rising: 1s sample urgency - When load approaches low threshold (±15%) while falling: 1s sample urgency - Prevents lag-causing profile misses - Reduce effective response time from ~13s to 3-5s for most workload changes - Critical lag scenarios: <1s detection and profile switch Defaults adjustment: - SAV_DYNAMIC_INTERVAL: 5 → 4 (base sample interval) - SAV_DYNAMIC_MIN_DELAY: 5 → 4 (min delay between profile changes) - Both now optimal for adaptive sampling and quick lag prevention Algorithm: - Track previous average load and sample times - Calculate load delta per sample cycle - Dynamically adjust sleep interval before next measurement - Predict when thresholds will be crossed based on trend - Enables responsive power profile switching without excessive polling This allows the daemon to catch sudden workload spikes that would previously cause lag while maintaining efficiency during stable periods.
|
@Mylinde Please don't invest any more time and effort into this. I will not be including load-dependent, dynamic profile switching in TLP. An explanation will follow. |
|
Sure, just close the PR after a short explanation. If you later like to have a look at it, I will keep this for my personal use in my fork, because it is working really nice. |
|
Closing this because still working on it. |
|
My view on the matter is this: The kernel governor controls P-states based on workload, which determines performance and power consumption. This control is based on a characteristic curve, the slope of which can be adjusted using the tunables platform_profile and energy_performance_preference. Something like TLP specifies the slope to the kernel by writing the tunable, and the kernel does all the work. That's TLP's basic principle, btw. In TLP a profile switch occurs automatically depending on the power source or manually at the user's request. All profiles are well defined by the configuration and do not change intransparently. With your "dynamic" approach, the slope also changes based on the load, resulting in a characteristic curve with two bend points. However, I do not find the technical complexity of this approach to be justified. Even using the conventional method, the kernel can always reach the minimum or maximum performance, regardless of the curve’s slope. I don't see any additional benefit regarding power consumption. You might want to create a standalone tool for dynamic, load-based profile switching that uses existing tools (TLP, power-profiles-daemon, tuned) as a backend by controlling them via the Power Profiles D-Bus API. Check out the HoldProfile method. The implementation of your daemon also has room for improvement:
|
|
Thank you for your explanation. Unless I’ve overlooked something, the dynamic SAV profile is now seamlessly integrated and is working flawlessly without any race conditions. In fact, it can’t generate any race conditions because it only runs when TLP is inactive. I’ve set I could definitely see a dedicated tool, perhaps a kind of fully dynamic, load-dependent AUTO-TLP. :) Thank you very much for your excellent work with TLP. |
Your question in was
I think this is a good idea. It could be a "smart" or "intelligent" way with a dynamic SAV daemon - workload-dependent power saver adjustments. I’ve given it some thought and created an initial function.
Logging is enabled and can be checked with:
sudo tail -f /tmp/dyn-saver.logFeatures:
Configuration:
Integration:
Complements platform-profile-autodetect (PR #875) for complete adaptive power management: