Skip to content

perf: Chart control performance improvements#379

Open
PaulAndersonS wants to merge 1 commit into
mainfrom
perf/chart-control-optimizations
Open

perf: Chart control performance improvements#379
PaulAndersonS wants to merge 1 commit into
mainfrom
perf/chart-control-optimizations

Conversation

@PaulAndersonS
Copy link
Copy Markdown
Collaborator

@PaulAndersonS PaulAndersonS commented May 29, 2026

Chart Control Performance Improvements

This PR consolidates 10 performance optimizations targeting hot paths in the Chart control — rendering, layout, data processing, and user interaction.

Changes

  1. Cache .ToList() outside loop (CartesianChartArea.cs) — Avoids repeated List allocation on every loop iteration in GetTotalWidth() and SBS positioning.

  2. Replace LINQ Where().Sum() with for loop (CartesianChartArea.cs) — Eliminates iterator allocations and delegate invocations in GetYValue().

  3. Replace .Cast<FastLineSegment>() with indexed for loop (FastLineSeries.cs) — Removes type-checking enumerator overhead in 3 hot rendering/hit-testing methods.

  4. Replace LINQ Where().OrderBy() with filter + List.Sort() (ChartTrackballBehavior.cs) — Eliminates intermediate array allocation and multi-pass enumeration during mouse tracking.

  5. Combine 4 LINQ Where().Min/Max() into single-pass loop (ErrorBarSegment.cs) — Reduces 4 full enumerations to 2 single-pass loops for min/max calculation.

  6. Skip InvalidateMeasure when value unchanged (DataLabelItemView.cs) — Prevents cascading layout invalidations when position is set to same value.

  7. Reuse PreviousPointInfos list (ChartTrackballBehavior.cs) — Uses Clear() + AddRange() instead of allocating a new list on every mouse move.

  8. Replace LINQ OrderBy with in-place List.Sort() (ChartTrackballBehavior.cs) — Avoids array allocation from collection expression in ValidateTrackballBehaviorForAllSeries.

  9. Replace Where().ToList() with RemoveAll() (HistogramSeries.cs) — Filters NaN values in-place instead of creating a new list copy.

  10. Remove unnecessary .ToList() allocation (StackingSeriesBase.cs) — Iterates visible series directly with inline check instead of creating intermediate filtered list.

Impact

  • Reduced GC pressure (fewer short-lived list allocations)
  • Faster rendering for charts with large datasets (100+ points)
  • Smoother trackball interaction (fewer allocations per mouse move)
  • Reduced layout thrashing from redundant invalidations

…ring

- Cache SideBySideSeriesPosition.Values.ToList() outside loop in GetTotalWidth()
- Replace LINQ Where().Sum() with for loop in GetYValue()
- Replace Cast<FastLineSegment>() foreach with direct index for loops in FastLineSeries
- Replace LINQ Where().OrderBy() with manual filter + List.Sort() in SmartLabelAlignment
- Replace four LINQ Where().Min/Max() calls with single-pass for loops in ErrorBarSegment
- Skip InvalidateMeasure when position value unchanged in DataLabelItemView
- Reuse PreviousPointInfos list via Clear+AddRange instead of new allocation per move
- Replace LINQ OrderBy with in-place List.Sort() in ValidateTrackballBehaviorForAllSeries
- Replace Where().ToList() with in-place RemoveAll in HistogramSeries
- Remove unnecessary ToList allocation in StackingSeriesBase.ResetVisibleSeries

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PaulAndersonS PaulAndersonS force-pushed the perf/chart-control-optimizations branch from d94614b to e41c059 Compare May 29, 2026 03:53
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