Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/BenchmarksApps/TechEmpower/BlazorSSR/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
builder.Services.AddRazorComponents();
builder.Services.AddSingleton(serviceProvider =>
{
// TODO: This custom configured HtmlEncoder won't actually be used until Blazor supports it: https://github.com/dotnet/aspnetcore/issues/47477
var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana);
settings.AllowCharacter('\u2014'); // allow EM DASH through
return HtmlEncoder.Create(settings);
Expand Down
27 changes: 26 additions & 1 deletion src/BenchmarksApps/TechEmpower/Minimal/Database/Db.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Data.Common;
using System.Data.Common;
using Dapper;
using Minimal.Models;

Expand Down Expand Up @@ -99,4 +99,29 @@ public async Task<List<Fortune>> LoadFortunesRows()

return result;
}

public Task<List<Fortune>> LoadFortunesRowsNoDb()
{
// Benchmark requirements explicitly prohibit pre-initializing the list size
var result = new List<Fortune>
{
new(1, "fortune: No such file or directory"),
new(2, "A computer scientist is someone who fixes things that aren't broken."),
new(3, "After enough decimal places, nobody gives a damn."),
new(4, "A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1"),
new(5, "A computer program does what you tell it to do, not what you want it to do."),
new(6, "Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen"),
new(7, "Any program that runs right is obsolete."),
new(8, "A list is only as strong as its weakest link. — Donald Knuth"),
new(9, "Feature: A bug with seniority."),
new(10, "Computers make very fast, very accurate mistakes."),
new(11, "<script>alert(\"This should not be displayed in a browser alert box.\");</script>"),
new(12, "フレームワークのベンチマーク"),
new(0, "Additional fortune added at request time.")
};

result.Sort(FortuneSortComparison);

return Task.FromResult(result);
}
}
63 changes: 63 additions & 0 deletions src/BenchmarksApps/TechEmpower/Minimal/FortunesRazorParameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using Minimal.Models;
using Minimal.Templates;

namespace Minimal;

internal readonly struct FortunesRazorParameters(List<Fortune> model) : IReadOnlyDictionary<string, object?>
{
private const string ModelKeyName = nameof(FortunesRazor.Model);

private readonly KeyValuePair<string, object?> _modelKvp = new(ModelKeyName, model);

public object? this[string key] => KeyIsModel(key) ? model : null;

public IEnumerable<string> Keys { get; } = [ModelKeyName];

public IEnumerable<object?> Values { get; } = [model];

public int Count { get; } = 1;

public bool ContainsKey(string key) => KeyIsModel(key);

public IEnumerator<KeyValuePair<string, object?>> GetEnumerator() => new Enumerator(_modelKvp);

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value)
{
if (KeyIsModel(key))
{
value = model;
return true;
}
value = default;
return false;
}

private static bool KeyIsModel(string key) => ModelKeyName.Equals(key, StringComparison.Ordinal);

private struct Enumerator(KeyValuePair<string, object?> kvp) : IEnumerator<KeyValuePair<string, object?>>
{
private bool _moved;

public readonly KeyValuePair<string, object?> Current { get; } = kvp;

readonly object IEnumerator.Current => Current;

public bool MoveNext()
{
if (_moved)
{
return false;
}
_moved = true;
return true;
}

public readonly void Dispose() { }

public void Reset() => throw new NotSupportedException();
}
}
22 changes: 17 additions & 5 deletions src/BenchmarksApps/TechEmpower/Minimal/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Microsoft.AspNetCore.Http.HttpResults;
using RazorSlices;
using Minimal;
using Minimal.Database;
using Minimal.Models;
Expand All @@ -23,6 +22,8 @@

// Add services to the container.
builder.Services.AddSingleton(new Db(appSettings));
builder.Services.AddRazorComponents();
builder.Services.AddSingleton(CreateHtmlEncoder());

var app = builder.Build();

Expand All @@ -38,15 +39,26 @@

app.MapGet("/db/result", async (Db db) => Results.Json(await db.LoadSingleQueryRow()));

var htmlEncoder = CreateHtmlEncoder();

app.MapGet("/fortunes", async (HttpContext context, Db db) => {
app.MapGet("/fortunes", async (HttpContext context, Db db, HtmlEncoder htmlEncoder) => {
var fortunes = await db.LoadFortunesRows();
//var fortunes = await db.LoadFortunesRowsNoDb(); // Don't call the database
var template = (RazorSliceHttpResult<List<Fortune>>)Fortunes.Create(fortunes);
template.HtmlEncoder = htmlEncoder;
return template;
});

app.MapGet("/fortunes/razor", async (HttpContext context, Db db) => {
var fortunes = await db.LoadFortunesRows();
//var fortunes = await db.LoadFortunesRowsNoDb(); // Don't call the database
var parameters = new Dictionary<string, object?> { { nameof(FortunesRazor.Model), fortunes } };
//var parameters = new FortunesRazorParameters(fortunes); // Custom parameters class to avoid allocating a Dictionary
var result = new RazorComponentResult<FortunesRazor>(parameters)
{
PreventStreamingRendering = true
};
return result;
});

app.MapGet("/queries/{count}", async (Db db, int count) => await db.LoadMultipleQueriesRows(count));

app.MapGet("/queries/{count}/result", async (Db db, int count) => Results.Json(await db.LoadMultipleQueriesRows(count)));
Expand All @@ -65,4 +77,4 @@ static HtmlEncoder CreateHtmlEncoder()
var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana);
settings.AllowCharacter('\u2014'); // allow EM DASH through
return HtmlEncoder.Create(settings);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>@foreach (var item in Model){<tr><td>@(new MarkupString(item.Id.ToString(CultureInfo.InvariantCulture)))</td><td>@item.Message</td></tr>}</table></body></html>
@code {
[Parameter]
public required List<Fortune> Model { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@using System.Globalization;
@using Minimal.Models;
4 changes: 2 additions & 2 deletions src/BenchmarksApps/TechEmpower/Minimal/minimal.benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ scenarios:
presetHeaders: html
path: /fortunes

fortunes_result:
fortunes_razor:
db:
job: postgresql
application:
Expand All @@ -87,7 +87,7 @@ scenarios:
job: wrk
variables:
presetHeaders: html
path: /fortunes/result
path: /fortunes/razor

single_query:
db:
Expand Down