Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: lablup/all-smi
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.17.6
Choose a base ref
...
head repository: lablup/all-smi
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.18.0
Choose a head ref
  • 9 commits
  • 24 files changed
  • 2 contributors

Commits on Apr 6, 2026

  1. feat: reduce TUI idle CPU with event-driven UI wakeups (#139)

    * feat: replace fixed-poll TUI loop with event-driven wakeup model
    
    Replace the 100ms event::poll() cadence with a tokio::select!-based
    coordinator that sleeps fully when idle. The UI now wakes only for
    terminal input, resize, fresh collector data, or animation ticks.
    
    - Add UiEventCoordinator with dedicated blocking terminal reader task
    - Add Notify channel from data collectors to UI loop for prompt refresh
    - Isolate animation ticks to fire only when animated elements are visible
    - Keyboard/mouse input is now independent of the polling interval
    
    Closes #135
    
    * fix: handle terminal reader channel closure in event coordinator
    
    Move the mpsc sender into the spawned blocking task instead of cloning
    it, so the channel closes naturally when the terminal reader exits.
    Add a TerminalClosed event variant to detect this in the select loop
    and shut down gracefully, preventing a potential hang when the terminal
    is lost and animations are inactive.
    
    * test: add unit tests for UiEventCoordinator and UiEvent
    
    Cover all UiEvent variants (DataReady, AnimationTick, TerminalClosed,
    Resize, TerminalInput), UiEventCoordinator construction and toggle
    methods, the data-ready notification path end-to-end with DataCollector,
    and sanity checks for the new ANIMATION_TICK_MS / TERMINAL_READER_POLL_MS
    AppConfig constants.
    inureyes authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    78511b5 View commit details
    Browse the repository at this point in the history
  2. feat: snapshot AppState before rendering to shorten critical section (#…

    …140)
    
    * feat: snapshot AppState before rendering to shorten TUI critical section
    
    Introduce a RenderSnapshot captured quickly from AppState under the
    mutex lock, then release the lock before expensive frame composition.
    This reduces contention between UI rendering and background data
    collectors.
    
    Key changes:
    - Add RenderSnapshot struct (render_snapshot.rs) with capture() method
      that clones only frame-needed data; VecDeque histories converted to
      Vec for lighter clone
    - Extract all frame assembly logic into FrameRenderer (frame_renderer.rs)
      operating purely on the snapshot without holding any lock
    - Refactor UiLoop::run() so the critical section only covers mutable
      bookkeeping (scroll offsets, frame counter) and snapshot capture;
      all rendering, differential output, and stdout flushing happen after
      the lock is dropped
    - RenderSnapshot::as_app_state() provides backward compatibility with
      existing UI functions that accept &AppState
    - Add 8 unit tests covering snapshot capture, independence, and
      roundtrip conversion
    
    Closes #136
    
    * fix: prevent overflow panics and eliminate redundant allocations in frame renderer
    
    - Use saturating_sub for all arithmetic in render_disconnection_notification
      to prevent subtraction overflow panic with long hostnames
    - Truncate text that exceeds box inner width instead of panicking
    - Add early return guard for degenerate box_width < 6
    - Pass shared view_state reference into render_gpu_section to eliminate a
      redundant as_app_state() allocation per frame
    - Pass cols/rows through to render_local_devices instead of making a
      redundant crossterm::terminal::size() syscall mid-render
    - Mark DEFAULT_TERMINAL_WIDTH/HEIGHT as dead_code now that the fallback
      is no longer needed in the render path
    
    * test: add unit tests for FrameRenderer covering smoke, geometry, and edge cases
    inureyes authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    6bb29c0 View commit details
    Browse the repository at this point in the history
  3. feat: cache derived TUI view data to avoid per-frame sorting and clon…

    …ing (#141)
    
    * feat: cache derived TUI view data to avoid per-frame sorting and cloning
    
    Introduce ViewCache that holds pre-computed sorted GPU indices,
    per-host filtered device subsets, and GPU-filtered process lists.
    Cache entries are keyed by data_version, current_tab, sort_criteria,
    and gpu_filter_enabled, and are only recomputed when those inputs
    change. This eliminates redundant filtering, sorting, and cloning
    on every render pass, particularly beneficial for large remote
    deployments with many GPUs and processes.
    
    * fix: guard against out-of-bounds tab index in GPU filtering paths
    
    Replace direct indexing of snapshot.tabs[current_tab] with
    .get() bounds-checked access in both the ViewCache GPU list
    builder and the frame renderer fallback path. When current_tab
    exceeds tabs.len(), the code now gracefully falls back to
    showing all GPUs instead of panicking.
    
    Also add Default impl for ViewCache per Rust conventions.
    inureyes authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    5c528e1 View commit details
    Browse the repository at this point in the history
  4. feat: trim hot-path rendering overhead in TUI frame assembly and diff…

    … pipeline (#142)
    
    * feat: trim hot-path rendering overhead in TUI frame assembly and diff pipeline
    
    Reduce per-frame work in the rendering pipeline after the architectural
    changes in #135, #136, and #137:
    
    Rendering pipeline refinement:
    - DifferentialRenderer accepts terminal dimensions from the caller,
      eliminating redundant terminal::size() syscalls on every frame
    - Replace FNV-1a full-content hashing with lightweight length-based
      identity check; per-line comparison already catches all differences
    - Only flush stdout when actual terminal writes occurred
    - Track change state to skip no-op flush operations
    
    Terminal housekeeping reductions:
    - Hide cursor once at session start instead of per-frame Hide/Show churn
    - Pass resize dimensions directly to DifferentialRenderer via
      update_dimensions() on resize events
    - Remove per-frame stdout acquisition for cursor operations
    
    Hot-path allocation cleanup:
    - print_colored_text: zero-allocation fast path when width is None
      (the common case), avoiding text.to_string() on every call
    - truncate_to_width: returns Cow<str> with zero-copy borrow when the
      string already fits, with an ASCII fast-path for byte-level slicing
    - Process renderer: reuse RowFormatter scratch buffer across rows,
      use write! into pre-sized buffers instead of per-field format! calls,
      borrow command string instead of cloning, use Cow<str> for GPU percent
      and GPU memory fields, reuse a single clear-line string for padding
    - draw_bar/draw_bar_multi: batch consecutive same-type segments into
      single print_colored_text calls instead of per-character emission,
      reducing terminal escape sequence count by ~50x per gauge
    - format_cpu_time: return Cow<str> to avoid allocation for common
      "0:00:00" case
    - format_hostname_with_scroll: build scroll window directly into a
      pre-sized String without intermediate extended-hostname allocation
    - BufferWriter: add reset() method for future frame-to-frame reuse
    
    Measurement support:
    - Add unit tests for BufferWriter throughput, DifferentialRenderer state
      management, and truncate_to_width allocation behavior
    - Add timing-based throughput tests for the render path
    
    * fix: remove dead identity check, guard non-ASCII hostnames, prevent infinite loop
    
    - DifferentialRenderer: remove dead content_bytes fast-check that never
      short-circuited; the per-line comparison is already the authoritative
      change-detection mechanism and is O(1) for identical strings
    - format_hostname_with_scroll: add ASCII guard before byte-level indexing
      to prevent character corruption on non-ASCII hostnames
    - draw_bar_multi: guarantee forward progress in segment batching loop
      when text overlay is behind current position
    
    * test: add unit tests for process_renderer and widgets hot-path functions
    
    Add test coverage for the optimized code paths introduced in this PR:
    - process_renderer: write_memory_size correctness, format_cpu_time Cow
      allocation behavior (zero/long-running borrows vs owned), RowFormatter
      scratch buffer reuse, and throughput measurements for the zero-seconds
      hot path
    - widgets: draw_bar and draw_bar_multi correctness (label, brackets,
      percentage text, custom text, long-label trimming) and escape-sequence
      batching verification confirming the ~50x reduction in terminal writes
      per gauge; includes throughput measurements for both functions
    inureyes authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    9509e14 View commit details
    Browse the repository at this point in the history

Commits on Apr 7, 2026

  1. fix: bypass render throttle for cursor/scroll input to restore respon…

    …siveness
    
    Scroll and cursor changes were gated behind the 100ms MIN_RENDER_INTERVAL_MS
    throttle, causing 50-100ms input lag on process list navigation. Now only
    data-driven updates from collectors are throttled; user-driven scroll changes
    render immediately.
    inureyes committed Apr 7, 2026
    Configuration menu
    Copy the full SHA
    5af4a4f View commit details
    Browse the repository at this point in the history
  2. fix: use actual visible process rows for scroll calculation

    The event handler hardcoded visible process rows as rows/2-1, but the
    actual process list area is much smaller due to GPU/CPU/memory/storage
    sections above it. This caused the cursor to scroll off-screen before
    the viewport followed. Now the renderer reports the real value and the
    event handler uses it for accurate scrolling.
    inureyes committed Apr 7, 2026
    Configuration menu
    Copy the full SHA
    8282c68 View commit details
    Browse the repository at this point in the history
  3. fix: keep periodic refresh tick active so idle TUI stays alive

    The event-driven model disabled animation ticks in local mode without
    marquee text, leaving DataReady (every 2-3s) as the only wakeup source.
    The display appeared frozen between data updates. Now the tick is never
    fully disabled: it runs at 200ms for animations and 1s for clock-only
    refresh. Tick events are also included in the render decision so the
    screen actually updates when they fire.
    inureyes committed Apr 7, 2026
    Configuration menu
    Copy the full SHA
    7636a50 View commit details
    Browse the repository at this point in the history
  4. docs: add protobuf-devel to Fedora/RHEL build prerequisites (#143)

    Add missing protobuf-devel package to dnf install command which provides
    well-known proto types (google/protobuf/timestamp.proto). Also add Linux
    build dependency instructions to the cargo install section in README.
    
    Closes #134
    inureyes authored Apr 7, 2026
    Configuration menu
    Copy the full SHA
    e66e6ee View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    f204d2a View commit details
    Browse the repository at this point in the history
Loading