Virtualization

Render only visible items for large lists.

Problem

10,000 items → 10,000 widgets → Slow

Solution

10,000 items → ~20 visible widgets → Fast

Virtual List

struct VirtualList {
    items: Vec<Item>,
    visible_range: Range<usize>,
    item_height: f32,
    scroll_offset: f32,
}

impl VirtualList {
    fn visible_items(&self) -> &[Item] {
        &self.items[self.visible_range.clone()]
    }
}

Calculating Visible Range

fn calculate_visible_range(&self, viewport_height: f32) -> Range<usize> {
    let start = (self.scroll_offset / self.item_height) as usize;
    let visible_count = (viewport_height / self.item_height).ceil() as usize + 1;
    let end = (start + visible_count).min(self.items.len());
    start..end
}

Scroll Handling

fn on_scroll(&mut self, delta: f32) {
    self.scroll_offset = (self.scroll_offset + delta)
        .max(0.0)
        .min(self.max_scroll());
    self.visible_range = self.calculate_visible_range(self.viewport_height);
}

Performance

ItemsWithout VirtualWith Virtual
1005ms5ms
1,00050ms5ms
10,000500ms5ms

Verified Test

#[test]
fn test_virtualization_range() {
    let item_height = 50.0;
    let viewport = 500.0;
    let scroll = 100.0;

    let start = (scroll / item_height) as usize;  // 2
    let count = (viewport / item_height).ceil() as usize + 1;  // 11

    assert_eq!(start, 2);
    assert_eq!(count, 11);
}