Summary
Every BindableObject eagerly allocates a Dictionary<TriggerBase, SetterSpecificity> at construction time, even though the vast majority of objects never use triggers. Lazy-initializing this field would eliminate a per-object heap allocation for all trigger-free elements.
Current behavior
|
internal Dictionary<TriggerBase, SetterSpecificity> _triggerSpecificity = new Dictionary<TriggerBase, SetterSpecificity>(); |
The dictionary is only accessed from TriggerBase attach/detach/query:
|
bindable._triggerSpecificity[this] = specificity; |
|
((SealedList<TriggerAction>)EnterActions).IsReadOnly = true; |
In a typical app, triggers are used on <5% of visual elements, but every Label, Button, Grid, StackLayout, etc. pays the allocation cost.
Proposed change
Lazy-initialize on first use:
// Before
internal Dictionary<TriggerBase, SetterSpecificity> _triggerSpecificity = new Dictionary<TriggerBase, SetterSpecificity>();
// After
internal Dictionary<TriggerBase, SetterSpecificity>? _triggerSpecificity;
The three call sites in TriggerBase.cs need minor updates:
- Attach (line 83):
(bindable._triggerSpecificity ??= new()).Add(this, specificity)
- Detach (line 93):
bindable._triggerSpecificity?.Remove(this)
- Query (line 109):
bindable._triggerSpecificity?.TryGetValue(this, out var specificity) == true
Estimated impact
An empty Dictionary<TriggerBase, SetterSpecificity> costs ~100 bytes. For a page with 200 elements: ~20 KB saved per page load.
Summary
Every
BindableObjecteagerly allocates aDictionary<TriggerBase, SetterSpecificity>at construction time, even though the vast majority of objects never use triggers. Lazy-initializing this field would eliminate a per-object heap allocation for all trigger-free elements.Current behavior
maui/src/Controls/src/Core/BindableObject.cs
Line 41 in 2c26b34
The dictionary is only accessed from
TriggerBaseattach/detach/query:maui/src/Controls/src/Core/Interactivity/TriggerBase.cs
Line 83 in 2c26b34
maui/src/Controls/src/Core/Interactivity/TriggerBase.cs
Line 93 in 2c26b34
maui/src/Controls/src/Core/Interactivity/TriggerBase.cs
Line 109 in 2c26b34
In a typical app, triggers are used on <5% of visual elements, but every
Label,Button,Grid,StackLayout, etc. pays the allocation cost.Proposed change
Lazy-initialize on first use:
The three call sites in
TriggerBase.csneed minor updates:(bindable._triggerSpecificity ??= new()).Add(this, specificity)bindable._triggerSpecificity?.Remove(this)bindable._triggerSpecificity?.TryGetValue(this, out var specificity) == trueEstimated impact
An empty
Dictionary<TriggerBase, SetterSpecificity>costs ~100 bytes. For a page with 200 elements: ~20 KB saved per page load.