gpui-performance
Performance optimization techniques for GPUI including rendering optimization, layout performance, memory management, and profiling strategies. Use when user needs to optimize GPUI application performance or debug performance issues.
What this skill does
# GPUI Performance Optimization
## Metadata
This skill provides comprehensive guidance on optimizing GPUI applications for rendering performance, memory efficiency, and overall runtime speed.
## Instructions
### Rendering Optimization
#### Understanding the Render Cycle
```
State Change → cx.notify() → Render → Layout → Paint → Display
```
**Key Points**:
- Only call `cx.notify()` when state actually changes
- Minimize work in `render()` method
- Cache expensive computations
- Reduce element count and nesting
#### Avoiding Unnecessary Renders
```rust
// BAD: Renders on every frame
impl MyComponent {
fn start_animation(&mut self, cx: &mut ViewContext<Self>) {
cx.spawn(|this, mut cx| async move {
loop {
cx.update(|_, cx| cx.notify()).ok(); // Forces rerender!
Timer::after(Duration::from_millis(16)).await;
}
}).detach();
}
}
// GOOD: Only render when state changes
impl MyComponent {
fn update_value(&mut self, new_value: i32, cx: &mut ViewContext<Self>) {
if self.value != new_value {
self.value = new_value;
cx.notify(); // Only notify on actual change
}
}
}
```
#### Optimize Subscription Updates
```rust
// BAD: Always rerenders on model change
let _subscription = cx.observe(&model, |_, _, cx| {
cx.notify(); // Rerenders even if nothing relevant changed
});
// GOOD: Selective updates
let _subscription = cx.observe(&model, |this, model, cx| {
let data = model.read(cx);
// Only rerender if relevant field changed
if data.relevant_field != this.cached_field {
this.cached_field = data.relevant_field.clone();
cx.notify();
}
});
```
#### Memoization Pattern
```rust
use std::cell::RefCell;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
struct MemoizedComponent {
model: Model<Data>,
cached_result: RefCell<Option<(u64, String)>>, // (hash, result)
}
impl MemoizedComponent {
fn expensive_computation(&self, cx: &ViewContext<Self>) -> String {
let data = self.model.read(cx);
// Calculate hash of input
let mut hasher = DefaultHasher::new();
data.relevant_fields.hash(&mut hasher);
let hash = hasher.finish();
// Return cached if unchanged
if let Some((cached_hash, cached_result)) = &*self.cached_result.borrow() {
if *cached_hash == hash {
return cached_result.clone();
}
}
// Compute and cache
let result = perform_expensive_computation(&data);
*self.cached_result.borrow_mut() = Some((hash, result.clone()));
result
}
}
```
### Layout Performance
#### Minimize Layout Complexity
```rust
// BAD: Deep nesting
div()
.flex()
.child(
div()
.flex()
.child(
div()
.flex()
.child(
div().child("Content")
)
)
)
// GOOD: Flat structure
div()
.flex()
.flex_col()
.gap_4()
.child("Header")
.child("Content")
.child("Footer")
```
#### Use Fixed Sizing When Possible
```rust
// BETTER: Fixed sizes (no layout calculation)
div()
.w(px(200.))
.h(px(100.))
.child("Fixed size")
// SLOWER: Dynamic sizing (requires layout calculation)
div()
.w_full()
.h_full()
.child("Dynamic size")
```
#### Avoid Layout Thrashing
```rust
// BAD: Reading layout during render
impl Render for BadComponent {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let width = cx.window_bounds().get_bounds().size.width;
// Using width immediately causes layout thrashing
div().w(width)
}
}
// GOOD: Cache layout-dependent values
struct GoodComponent {
cached_width: Pixels,
}
impl GoodComponent {
fn on_window_resize(&mut self, cx: &mut ViewContext<Self>) {
let width = cx.window_bounds().get_bounds().size.width;
if self.cached_width != width {
self.cached_width = width;
cx.notify();
}
}
}
```
#### Virtual Scrolling for Long Lists
```rust
struct VirtualList {
items: Vec<String>,
scroll_offset: f32,
viewport_height: f32,
item_height: f32,
}
impl Render for VirtualList {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
// Calculate visible range
let start_index = (self.scroll_offset / self.item_height).floor() as usize;
let visible_count = (self.viewport_height / self.item_height).ceil() as usize;
let end_index = (start_index + visible_count).min(self.items.len());
// Only render visible items
div()
.h(px(self.viewport_height))
.overflow_y_scroll()
.on_scroll(cx.listener(|this, event, cx| {
this.scroll_offset = event.scroll_offset.y;
cx.notify();
}))
.child(
div()
.h(px(self.items.len() as f32 * self.item_height))
.child(
div()
.absolute()
.top(px(start_index as f32 * self.item_height))
.children(
self.items[start_index..end_index]
.iter()
.map(|item| {
div()
.h(px(self.item_height))
.child(item.as_str())
})
)
)
)
}
}
```
### Memory Management
#### Preventing Memory Leaks
```rust
// LEAK: Subscription not stored
impl BadView {
fn new(model: Model<Data>, cx: &mut ViewContext<Self>) -> Self {
cx.observe(&model, |_, _, cx| cx.notify()); // Leak!
Self { model }
}
}
// CORRECT: Store subscription
struct GoodView {
model: Model<Data>,
_subscription: Subscription, // Cleaned up on Drop
}
impl GoodView {
fn new(model: Model<Data>, cx: &mut ViewContext<Self>) -> Self {
let _subscription = cx.observe(&model, |_, _, cx| cx.notify());
Self { model, _subscription }
}
}
```
#### Avoid Circular References
```rust
// BAD: Circular reference
struct CircularRef {
self_view: Option<View<Self>>, // Circular!
}
// GOOD: Use weak references or redesign
struct NoCycle {
other_view: View<OtherView>, // No cycle
}
```
#### Bounded Collections
```rust
use std::collections::VecDeque;
const MAX_HISTORY: usize = 100;
struct BoundedHistory {
items: VecDeque<Item>,
}
impl BoundedHistory {
fn add_item(&mut self, item: Item) {
self.items.push_back(item);
// Maintain size limit
while self.items.len() > MAX_HISTORY {
self.items.pop_front();
}
}
}
```
#### Reuse Allocations
```rust
struct BufferedComponent {
buffer: String, // Reused across operations
}
impl BufferedComponent {
fn format_data(&mut self, data: &[Item]) -> &str {
self.buffer.clear(); // Reuse allocation
for item in data {
use std::fmt::Write;
write!(&mut self.buffer, "{}\n", item.name).ok();
}
&self.buffer
}
}
```
### Profiling Strategies
#### CPU Profiling with cargo-flamegraph
```bash
# Install
cargo install flamegraph
# Profile application
cargo flamegraph --bin your-app
# With specific features
cargo flamegraph --bin your-app --features profiling
# Opens flamegraph.svg showing CPU time distribution
```
#### Memory Profiling
```bash
# valgrind (Linux)
valgrind --tool=massif --massif-out-file=massif.out ./target/release/your-app
ms_print massif.out
# heaptrack (Linux)
heaptrack ./target/release/your-app
heaptrack_gui heaptrack.Related in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.