Skip to content

perf: Chart control performance improvements#390

Open
PaulAndersonS wants to merge 2 commits into
mainfrom
paulandersons/cuddly-eureka
Open

perf: Chart control performance improvements#390
PaulAndersonS wants to merge 2 commits into
mainfrom
paulandersons/cuddly-eureka

Conversation

@PaulAndersonS

Copy link
Copy Markdown
Collaborator

Root Cause of the Issue

Multiple hot paths in the Chart control allocate unnecessary temporary collections (via LINQ .Reverse(), .Where().ToList(), .Values.ToList(), LINQ query syntax) and perform redundant scans (multiple .Min()/.Max() calls) on every frame or data update.

Description of Change

This PR implements 8 performance improvements targeting allocation reduction and redundant computation elimination in the Chart control:

# Improvement Impact File
1 Replace LINQ .Reverse() with backward for loop HIGH SfCartesianChart.cs
2 Replace .Where().ToList() with direct iteration HIGH CartesianChartArea.cs
3 (Already optimized in codebase)
4 Cache .Values.ToList() outside loops MEDIUM CartesianChartArea.cs
5 (PathF lacks Clear() - not feasible)
6 Cache yPropertyAccessor.Count in data binding loops MEDIUM ChartSeriesPartial.cs
7 Replace LINQ query syntax with pre-sized List<double> loops MEDIUM CartesianSeries.cs
8 Remove .Where().ToList() allocation in UpdateSbsSeries MEDIUM CartesianSeries.cs
9 Cache StrokeDashArray.ToFloatArray() result per segment MEDIUM AreaSegment.cs
10 Replace multiple LINQ .Min()/.Max()/.Where() scans with single loop MEDIUM AreaSegment.cs

Key benefits:

  • Eliminates per-frame allocations from LINQ .Reverse() and .ToList() in hit-testing and rendering paths
  • Removes redundant list materialization in side-by-side series calculation loops
  • Caches dash pattern array conversion to avoid per-frame allocation
  • Reduces SetData from 5+ collection scans to a single pass

Issues Fixed

Performance improvement - no specific issue

Screenshots

N/A - performance-only changes with no visual impact

- Replace LINQ .Reverse() with backward for loop in SfCartesianChart
- Replace .Where().ToList() with direct iteration in CartesianChartArea
- Cache .Values.ToList() outside loops in CartesianChartArea
- Replace LINQ query syntax with pre-sized List loops in CartesianSeries
- Remove .Where().ToList() allocation in CartesianSeries.UpdateSbsSeries
- Cache yPropertyAccessor.Count in data binding loops in ChartSeriesPartial
- Cache StrokeDashArray.ToFloatArray() result in AreaSegment
- Replace multiple LINQ .Min()/.Max() scans with single loop in AreaSegment.SetData

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants