Skip to content

Refactor/11850 Flow_threads refactor: unify recycler and manager computation v1 - #40

Closed
KEIAHNY wants to merge 1 commit into
mainfrom
11850-refactor-flow_threads-v1
Closed

KEIAHNY wants to merge 1 commit into
mainfrom
11850-refactor-flow_threads-v1

Conversation

@KEIAHNY

@KEIAHNY KEIAHNY commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

PR Type

Enhancement


Description

  • Extract shared get_up_windows window-detection logic

  • Add get_window_cpu_average_vector CPU averaging helper

  • Generalize threshold checks via above direction parameter

  • Reset up flag per window, fixing stale state


Diagram Walkthrough

flowchart LR
  recycler["get_recycler_count"] -- "HUBER_THRESHOLD, above=true" --> upw["get_up_windows"]
  manager["manager count logic"] -- "MANAGER_SLOPE, above=false" --> upw
  upw -- "per-window CPU averages" --> cpu["get_window_cpu_average_vector"]
Loading

File Walkthrough

Relevant files
Enhancement
flow_threads.rs
Unify recycler and manager window computation logic           

src/flow_threads.rs

  • Extract duplicated window-scanning loop into generic get_up_windows
    with threshold and above parameters
  • Add get_window_cpu_average_vector helper for per-window CPU usage
    averaging
  • Rewrite get_recycler_count and manager count logic to reuse
    get_up_windows
  • Reset up flag each outer-loop iteration and fix misplaced closing
    brace
+67/-103

@KEIAHNY KEIAHNY self-assigned this Oct 12, 2026
@github-actions

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Dropped CPU check

The old manager-count logic required both the slope to be below MANAGER_SLOPE and the window average CPU usage to exceed CPU_USAGE_MAX for a window to count as "up". The unified get_up_windows only performs the threshold comparison and never uses the computed avg, so the CPU_USAGE_MAX check is silently dropped for the manager path. This changes behavior: manager windows with low CPU usage now qualify, which can inflate slope_vector and alter the computed mgr_power. The unused avg variable also indicates the CPU check was meant to be carried over.

let avg: f32 = avg_cpu_usage[(sm_counter * (avg_cpu_usage.len()/WINDOWS as usize)) ..
    ((sm_counter + 1) * (avg_cpu_usage.len()/WINDOWS as usize))]
    .iter().sum::<f32>() / (avg_cpu_usage.len()/WINDOWS as usize) as f32;
sm_counter+=1;

if (above && current_window > &threshold) || (!above && current_window < &threshold) {
    tmp_slope_vector.push(*current_window);
Dead computation

Inside get_up_windows, avg is computed on every iteration of the inner loop (including slicing and summing avg_cpu_usage) but is never read, since the CPU_USAGE_MAX check was removed. This is dead work per window element and will produce an unused-variable compiler warning; either restore the CPU-usage check or remove the computation and the sm_counter bookkeeping.

let avg: f32 = avg_cpu_usage[(sm_counter * (avg_cpu_usage.len()/WINDOWS as usize)) ..
    ((sm_counter + 1) * (avg_cpu_usage.len()/WINDOWS as usize))]
    .iter().sum::<f32>() / (avg_cpu_usage.len()/WINDOWS as usize) as f32;
sm_counter+=1;
Dead clear call

current_windows.clear() at the end of the loop body is dead code: current_windows is unconditionally reassigned via .to_vec() at the top of the next iteration, so clearing it has no effect. Harmless, but misleading.

current_windows.clear();

@github-actions

Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Restore dropped CPU usage check in unified window logic

The avg CPU usage is computed but never used, which means the manager path lost its
if avg > CPU_USAGE_MAX check that existed before the refactor. As a result,
get_flow_manager_count no longer verifies that managers are busy enough before
collecting a window, silently changing the manager computation logic. Add an
optional CPU threshold parameter to get_up_windows (e.g. cpu_threshold: Option),
pass None from the recycler path and Some(CPU_USAGE_MAX) from the manager path, and
apply the check after the slope check.

src/flow_threads.rs [88-100]

             for current_window in &current_windows {
                 let avg: f32 = avg_cpu_usage[(sm_counter * (avg_cpu_usage.len()/WINDOWS as usize)) ..
                     ((sm_counter + 1) * (avg_cpu_usage.len()/WINDOWS as usize))]
                     .iter().sum::<f32>() / (avg_cpu_usage.len()/WINDOWS as usize) as f32;
                 sm_counter+=1;
 
                 if (above && current_window > &threshold) || (!above && current_window < &threshold) {
                     tmp_slope_vector.push(*current_window);
                     up &= true;
                 }
                 else {
                     up &= false;
                     break;
                 }
+
+                if let Some(cpu_max) = cpu_threshold {
+                    if avg > cpu_max {
+                        up &= true;
+                    }
+                    else {
+                        up &= false;
+                        break;
+                    }
+                }
             }
Suggestion importance[1-10]: 8

__

Why: Correct and important: the refactor into get_up_windows silently dropped the if avg > CPU_USAGE_MAX check from the manager path (it existed in the old get_flow_manager_count code), and avg is now computed but unused. This changes manager scaling behavior; adding an optional CPU threshold parameter restores the lost logic.

Medium
Guard against out-of-bounds window slicing

*If result has a length that is not a multiple of WINDOWS (including the empty case),
the slice result[(counter*WINDOWS)..((counter+1)WINDOWS)] will panic, and an empty
current_windows makes the subsequent .last().expect(...) panic as well as leaving
tmp_slope_vector empty while up stays true (leading to a division by zero for the
average). Guard the loop with a bounds check before slicing so it terminates
gracefully instead of panicking.

src/flow_threads.rs [83-86]

         loop {
+            if ((counter + 1) * WINDOWS) as usize > result.len() {
+                break;
+            }
+
             avg_cpu_usage = Self::get_window_cpu_average_vector(cpu_usages, num_elements, counter);
 
             current_windows = result[(counter*WINDOWS) as usize..((counter+1)*WINDOWS) as usize].to_vec();
Suggestion importance[1-10]: 4

__

Why: The bounds check is technically valid since a non-multiple result length would panic on slicing, and an empty current_windows would panic on .last().expect(...). However, this is a defensive error-handling improvement for an edge case that also existed in the pre-PR code, so its impact is moderate.

Low
General
Prevent NaN from empty average divisions

now_recycled is built with .windows(2), so if the recycled window slice contains
fewer than two elements the resulting vector is empty and the division produces NaN,
which then propagates into RecyclerUp and the downstream max_by comparison on
queue_growth. Guard both averages against empty vectors to avoid NaN poisoning the
recycler count computation.

src/flow_threads.rs [157-158]

-            recycler_up.now_in_queue_avg = now_in_queue.iter().sum::<f64>() / now_in_queue.len() as f64;
-            recycler_up.now_recycled_avg = now_recycled.iter().sum::<f64>() / now_recycled.len() as f64;
+            recycler_up.now_in_queue_avg = if now_in_queue.is_empty() { 0.0 } else { now_in_queue.iter().sum::<f64>() / now_in_queue.len() as f64 };
+            recycler_up.now_recycled_avg = if now_recycled.is_empty() { 0.0 } else { now_recycled.iter().sum::<f64>() / now_recycled.len() as f64 };
Suggestion importance[1-10]: 4

__

Why: The suggestion correctly identifies that now_recycled from .windows(2) could be empty and produce NaN. It is a reasonable defensive fix, but it addresses an unlikely edge case (slices sized WINDOWS * num_elements) rather than a clear bug, so impact is limited.

Low
  • Author self-review: I have reviewed the PR code suggestions, and addressed the relevant ones.

@KEIAHNY

KEIAHNY commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator Author

Applying Dead clear call issue, otherwise are suggestions nonsense.

@KEIAHNY KEIAHNY closed this Oct 12, 2026
@KEIAHNY
KEIAHNY deleted the 11850-refactor-flow_threads-v1 branch October 12, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant