dotnet / dotnet/aspnetcore

Blazor Server RenderBatchWriter should stop defensive copies of RenderTreeFrame on Write method

Open
#25,764 3 comments 0 reactions 0 assignees View on GitHub
affected-all area-blazor bug feature-rendering Perf Pillar: Technical Debt Priority:2 severity-nice-to-have
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

In .NET 5, `RenderTreeFrame` stopped being `readonly` in order to support some performance optimizations focused on WebAssembly. Generally this did not have any drawbacks because:

* The mutability is `internal`. We didn't make it publicly mutable.
* The framework always passes around `RenderTreeFrame` either with `ref` or with no modifier
* Or in the case of `RenderTreeDiffBuilder.NextSiblingIndex`, it does use `in` but it doesn't make any method calls or property accesses inside it (we probably should change this to use `ref` to have the behavior be more obvious).

However there remains one other case: `RenderBatchWriter`'s `Write` method:

```cs
void Write(in RenderTreeFrame frame)
{
....
}
```

Inside there, it performs lots of property reads. If this [blog post about perf implications of `in`](https://devblogs.microsoft.com/premier-developer/the-in-modifier-and-the-readonly-structs-in-c/) is correct, that means there will be lots of defensive copies happening.

To fix this, we could either remove the `in` modifier and just have a single copy made for each call to `Write`, or we could replace `in` with `ref` and have no copies made.

I don't yet have any specific measurement of the perf effects. We should at least try to measure this before committing to a specific resolution. It might not really have any observable real-world effects because `RenderBatchWriter` is so fast anyway relative to other things that are going on, such as transmitting render batches over the network.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.