Skip to content

Blazor ComponentBase.SetParametersAsync(ParameterView.Empty) still create costly WriterForType despite ParameterView.Empty #44693

Closed as not planned
@sake402

Description

@sake402

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

For performance reasons and faster startup, we have created a source generator that the automate the generation of Blazor Component's SetParameterAsync like this

    public partial class FooComponent
    {
        public override Task SetParametersAsync(ParameterView parameters)
        {
            foreach (var parameter in parameters)
            {
                switch (parameter.Name)
                {
                    case nameof(Value):
                    	Value = (System.Func<bool>)parameter.Value;
                    break;
                    case nameof(Show):
                    	Show = (LivingThing.Core.Frameworks.Common.Data.Subscription<bool>)parameter.Value;
                    break;
                    case nameof(Render):
                    	Render = (LivingThing.Core.Frameworks.Common.Data.Subscription<bool>)parameter.Value;
                    break;
                    case nameof(Control):
                    	Control = (LivingThing.Core.Frameworks.Client.Components.RenderControl)parameter.Value;
                    break;
                }
            }
            return base.SetParametersAsync(ParameterView.Empty);
        }
    }

After setting all our parameters, we call base.SetParametersAsync(ParameterView.Empty) so as to raise lifecycle event neccessary.

However, the codebase for ComponentBase.SetParametersAsync(ParameterView.Empty) is this

public virtual Task SetParametersAsync(ParameterView parameters)
        {
            parameters.SetParameterProperties(this);
            if (!_initialized)
            {
                _initialized = true;

                return RunInitAndSetParametersAsync();
            }
            else
            {
                return CallOnParametersSetAsync();
            }
        }

The line parameters.SetParameterProperties(this); calls into a codebase that instantiate the writer for this component, despite this is no longer needed and ends up wasting the precious time we are trying to save as well as memory (if you have a lot of components).

 var targetType = target.GetType();
            if (!_cachedWritersByType.TryGetValue(targetType, out var writers))
            {
                writers = new WritersForType(targetType); //This is very expensive as it does a lot of reflection
                _cachedWritersByType[targetType] = writers;
            }

I am proposing a pre-check on ParameterView in line parameters.SetParameterProperties(this); such that if the parameters is empty, there is no need to call parameters.SetParameterProperties(this); to avoid the startup cost

if (!parameters.IsEmpty){
parameters.SetParameterProperties(this);
}

Expected Behavior

No need to call parameters.SetParameterProperties(this); on empty ParameterView

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

No response

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions