-
Notifications
You must be signed in to change notification settings - Fork 9.8k
/
RenderTreeDiffBuilderBenchmark.cs
111 lines (91 loc) · 4 KB
/
RenderTreeDiffBuilderBenchmark.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Components.Performance;
public class RenderTreeDiffBuilderBenchmark
{
private readonly Renderer renderer;
private readonly RenderTreeBuilder original;
private readonly RenderTreeBuilder modified;
private readonly RenderBatchBuilder builder;
public RenderTreeDiffBuilderBenchmark()
{
builder = new RenderBatchBuilder();
renderer = new FakeRenderer();
// A simple component for basic tests -- this is similar to what MVC scaffolding generates
// for bootstrap3 form fields, but modified to be more Component-like.
original = new RenderTreeBuilder();
original.OpenElement(0, "div");
original.AddAttribute(1, "class", "form-group");
original.OpenElement(2, "label");
original.AddAttribute(3, "class", "control-label");
original.AddAttribute(4, "for", "name");
original.AddAttribute(5, "data-unvalidated", true);
original.AddContent(6, "Car");
original.CloseElement();
original.OpenElement(7, "input");
original.AddAttribute(8, "class", "form-control");
original.AddAttribute(9, "type", "text");
original.AddAttribute(10, "name", "name"); // Notice the gap in sequence numbers
original.AddAttribute(12, "value", "");
original.CloseElement();
original.OpenElement(13, "span");
original.AddAttribute(14, "class", "text-danger field-validation-valid");
original.AddContent(15, "");
original.CloseElement();
original.CloseElement();
// Now simulate some input
modified = new RenderTreeBuilder();
modified.OpenElement(0, "div");
modified.AddAttribute(1, "class", "form-group");
modified.OpenElement(2, "label");
modified.AddAttribute(3, "class", "control-label");
modified.AddAttribute(4, "for", "name");
modified.AddAttribute(5, "data-unvalidated", false);
modified.AddContent(6, "Car");
modified.CloseElement();
modified.OpenElement(7, "input");
modified.AddAttribute(8, "class", "form-control");
modified.AddAttribute(9, "type", "text");
modified.AddAttribute(10, "name", "name");
modified.AddAttribute(11, "data-validation-state", "invalid");
modified.AddAttribute(12, "value", "Lamborghini");
modified.CloseElement();
modified.OpenElement(13, "span");
modified.AddAttribute(14, "class", "text-danger field-validation-invalid"); // changed
modified.AddContent(15, "No, you can't afford that.");
modified.CloseElement();
modified.CloseElement();
}
[Benchmark(Description = "RenderTreeDiffBuilder: Input and validation on a single form field.", Baseline = true)]
public void ComputeDiff_SingleFormField()
{
builder.ClearStateForCurrentBatch();
var diff = RenderTreeDiffBuilder.ComputeDiff(renderer, builder, 0, modified.GetFrames(), original.GetFrames(), original.GetNamedEvents());
GC.KeepAlive(diff);
}
private sealed class FakeRenderer : Renderer
{
public FakeRenderer()
: base(new TestServiceProvider(), NullLoggerFactory.Instance)
{
}
public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault();
protected override void HandleException(Exception exception)
{
throw new NotImplementedException();
}
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
=> Task.CompletedTask;
}
private sealed class TestServiceProvider : IServiceProvider
{
public object GetService(Type serviceType)
{
return null;
}
}
}