Skip to content

Perf: Reduce allocations across 5 controls with targeted optimizations#377

Open
PaulAndersonS wants to merge 1 commit into
mainfrom
paulandersons/psychic-chainsaw
Open

Perf: Reduce allocations across 5 controls with targeted optimizations#377
PaulAndersonS wants to merge 1 commit into
mainfrom
paulandersons/psychic-chainsaw

Conversation

@PaulAndersonS
Copy link
Copy Markdown
Collaborator

Root Cause of the Issue

Multiple controls allocate unnecessary collections (List, Array) in frequently-called methods, causing GC pressure and reducing throughput during layout, rendering, and user interaction.

Description of Change

Five targeted performance improvements that reduce heap allocations:

  1. OtpInput (SfOtpInput.cs) — Replaced O(n²) Concat(new[]{x}).ToArray() pattern in AddEntry, SetInputFieldPosition, and SetSeparatorPosition with a List<T>-based approach that builds the collection once and converts to array at the end.

  2. Carousel iOS (PlatformCarousel.iOS.cs) — Replaced .ToList().ForEach(...) with a direct foreach loop, eliminating a List allocation. Also cached the IsInteractionEnable() result to avoid calling it N+1 times.

  3. SfView (SfView.cs) — Removed the redundant .AsReadOnly() wrapper in GetVisualChildren(), which allocated an extra ReadOnlyCollection<T> on every call. List<T> already implements IReadOnlyList<T>.

  4. DatePicker (SfDatePicker.cs, DatePickerHelper.cs) — Replaced MonthNames.ToList().IndexOf(...) with Array.IndexOf(MonthNames, ...), eliminating 4 separate List allocations per month-selection event.

  5. ProgressBar (SfLinearProgressBar.cs, SfCircularProgressBar.cs) — Replaced LINQ OrderBy(...).ToList() with new List<T>(source) + List.Sort() for in-place sorting of gradient stops, eliminating the intermediate iterator and sort buffer allocations.

Issues Fixed

N/A — proactive performance improvement

Unit Tests Added

  • DatePickerMonthIndexUnitTests — Verifies Array.IndexOf produces identical results to the previous List.IndexOf approach for all month name formats
  • LinearProgressBarGradientSortUnitTests — Verifies gradient stops are correctly handled after the sort optimization (out-of-order, single-stop, already-sorted scenarios)

1. OtpInput: Replace O(n²) Concat().ToArray() pattern with List-based
   collection building in AddEntry/SetInputFieldPosition/SetSeparatorPosition
2. Carousel (iOS): Replace .ToList().ForEach() with direct foreach loop,
   also cache IsInteractionEnable() result to avoid repeated calls
3. SfView: Remove redundant .AsReadOnly() wrapper in GetVisualChildren()
4. DatePicker: Replace .ToList().IndexOf() with Array.IndexOf() to avoid
   heap allocation when looking up month names
5. ProgressBar: Replace LINQ OrderBy().ToList() with List.Sort() for
   in-place sorting of gradient stops

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@MuniappanSubramanian MuniappanSubramanian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date Picker code changes are fine

@PaulAndersonS PaulAndersonS added this to the v1.0.11 milestone May 29, 2026
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