Skip to content

Update from task 9b59ce5b-a9a9-40b3-a7c9-01c7a72b1fd2 - #3

Open
vindeckyy wants to merge 1 commit into
mainfrom
code-optimization-tips-b1fd2
Open

Update from task 9b59ce5b-a9a9-40b3-a7c9-01c7a72b1fd2#3
vindeckyy wants to merge 1 commit into
mainfrom
code-optimization-tips-b1fd2

Conversation

@vindeckyy

@vindeckyy vindeckyy commented Aug 3, 2026

Copy link
Copy Markdown
Owner

This PR was created by qwen-chat coder for task 9b59ce5b-a9a9-40b3-a7c9-01c7a72b1fd2.

Summary by CodeRabbit

  • Performance

    • Improved fan-curve interpolation for faster response.
    • Reduced repeated hardware sensor lookups through caching.
    • Added short-term caching for GPU temperature readings, including unavailable readings.
  • Reliability

    • Fan control now retains recent sensor and duty-cycle state, helping provide more consistent behavior when readings are temporarily unavailable.

Key features implemented:
- Replaced linear interpolation loop with binary search algorithm in fan-daemon.py for O(log n) temperature curve lookups
- Updated GUI interpolation logic in fan-gui.py to use binary search for improved performance
- Added bisect_left import to support optimized interpolation calculations
- Maintained identical functionality while significantly reducing computational complexity

The changes optimize temperature curve interpolation from O(n) to O(log n) using binary search, improving performance especially with larger fan curves while maintaining all existing functionality.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Fan runtime behavior

Layer / File(s) Summary
Binary-search fan curve interpolation
fan-daemon.py, fan-gui.py
Both implementations use bisect_left to select curve segments. Endpoint handling and duty calculations remain in place.
Daemon sensor caching
fan-daemon.py
CPU sensor discovery and GPU temperature reads now use module-level caches. GPU failures are cached for one second.
GUI runtime state
fan-gui.py
Sensor history, EC readback, and fan-duty tracking state are initialized earlier. Duplicate declarations were removed.

Repository ignore policy

Layer / File(s) Summary
Ignore pattern removal
.gitignore
The file no longer ignores Python cache files, compiled files, or macOS metadata.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: hayden

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description omits the required Summary, Validation, Hardware impact, and acknowledgement sections. Use the repository template and document the changes, validation results, hardware impact, and unofficial project acknowledgement.
Title check ❓ Inconclusive The title identifies the task but does not describe the binary-search optimization or related changes. Replace the task identifier with a concise summary of the primary change, such as optimizing fan-curve interpolation with binary search.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch code-optimization-tips-b1fd2

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
fan-daemon.py (2)

39-80: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Cache the negative CPU sensor result.

Line 69 treats None as an uninitialized cache value. Line 80 therefore causes a full /sys/class/hwmon scan on every call when k10temp is absent. Use a distinct sentinel for the uninitialized state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fan-daemon.py` around lines 39 - 80, Update find_cpu_sensor and _sensor_cache
to use a distinct uninitialized sentinel rather than None, so a completed scan
with no k10temp sensor is cached as a negative result and subsequent calls skip
rescanning.

150-175: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Cache failed GPU lookups.

Line 157 only reuses non-None values. Failed commands, nonzero exit codes, and empty output therefore invoke nvidia-smi again on the next call. Also, now is captured before subprocess.run, so a command that exceeds one second returns an already-expired cache entry. Initialize _gpu_temp_time to None, use its presence as the cache-validity marker, and set it after the command completes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fan-daemon.py` around lines 150 - 175, Update gpu_temp and the cache globals
to use _gpu_temp_time = None as the validity marker, allowing cached None
results from command failures, nonzero exits, and empty output to be reused
during _GPU_CACHE_TTL. Check the timestamp for presence rather than requiring
_gpu_temp_cache to be non-None, and capture/set the cache timestamp after
subprocess.run completes, including the exception path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.gitignore:
- Line 1: Restore the .gitignore rules for __pycache__/, *.pyc, and .DS_Store,
and ensure any explanatory text is prefixed with # so Git interprets it as a
comment rather than an ignore pattern.

In `@fan-daemon.py`:
- Around line 204-208: The interpolation logic in fan-daemon.py lines 204-208
and fan-gui.py lines 135-139 rebuilds a temperature list on every call. Update
both functions to use a shared direct or precomputed temperature-index
representation with bisect_left, preserving identical interpolation behavior
while avoiding per-call O(n) traversal and allocation.

---

Outside diff comments:
In `@fan-daemon.py`:
- Around line 39-80: Update find_cpu_sensor and _sensor_cache to use a distinct
uninitialized sentinel rather than None, so a completed scan with no k10temp
sensor is cached as a negative result and subsequent calls skip rescanning.
- Around line 150-175: Update gpu_temp and the cache globals to use
_gpu_temp_time = None as the validity marker, allowing cached None results from
command failures, nonzero exits, and empty output to be reused during
_GPU_CACHE_TTL. Check the timestamp for presence rather than requiring
_gpu_temp_cache to be non-None, and capture/set the cache timestamp after
subprocess.run completes, including the exception path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b75dffe-bcd8-4127-9762-99edca256c55

📥 Commits

Reviewing files that changed from the base of the PR and between ec6dccb and f99c4bb.

⛔ Files ignored due to path filters (2)
  • __pycache__/fan-daemon.cpython-312.pyc is excluded by !**/*.pyc
  • __pycache__/fan-gui.cpython-312.pyc is excluded by !**/*.pyc
📒 Files selected for processing (3)
  • .gitignore
  • fan-daemon.py
  • fan-gui.py

Comment thread .gitignore
__pycache__/
*.pyc
.DS_Store No newline at end of file
Nothing should be ignored since only Python source files (.py) were modified and no build artifacts, dependencies, or temporary files are present in the changes. No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Restore the ignore rules for generated files.

Line [1] is not a comment. Git treats it as a literal ignore pattern. Removing __pycache__/, *.pyc, and .DS_Store allows generated files and local metadata to be committed accidentally. Restore these patterns and prefix any explanation with #.

Proposed fix
-Nothing should be ignored since only Python source files (.py) were modified and no build artifacts, dependencies, or temporary files are present in the changes.
+__pycache__/
+*.pyc
+.DS_Store
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Nothing should be ignored since only Python source files (.py) were modified and no build artifacts, dependencies, or temporary files are present in the changes.
__pycache__/
*.pyc
.DS_Store
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.gitignore at line 1, Restore the .gitignore rules for __pycache__/, *.pyc,
and .DS_Store, and ensure any explanatory text is prefixed with # so Git
interprets it as a comment rather than an ignore pattern.

Comment thread fan-daemon.py
Comment on lines +204 to +208
temps = [p[0] for p in curve]
idx = bisect_left(temps, temp) - 1
t0, d0 = curve[idx]
t1, d1 = curve[idx + 1]
return d0 + (d1 - d0) * (temp - t0) / (t1 - t0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Avoid rebuilding the temperature index for every interpolation.

Both functions create temps with an O(n) traversal before bisect_left. This removes the intended O(log n) lookup benefit and adds an allocation on each control-loop iteration. Bisect directly on the normalized (temperature, duty) tuples, or store a temperature index with the curve.

  • fan-daemon.py#L204-L208: replace the per-call temps list with a direct or precomputed index lookup.
  • fan-gui.py#L135-L139: apply the same lookup representation to preserve daemon and GUI behavior.
📍 Affects 2 files
  • fan-daemon.py#L204-L208 (this comment)
  • fan-gui.py#L135-L139
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fan-daemon.py` around lines 204 - 208, The interpolation logic in
fan-daemon.py lines 204-208 and fan-gui.py lines 135-139 rebuilds a temperature
list on every call. Update both functions to use a shared direct or precomputed
temperature-index representation with bisect_left, preserving identical
interpolation behavior while avoiding per-call O(n) traversal and allocation.

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.

2 participants