diff --git a/frameworks/CSharp/aspnetcore/README.md b/frameworks/CSharp/aspnetcore/README.md
index 2e0ddeab3b4..00092de375d 100644
--- a/frameworks/CSharp/aspnetcore/README.md
+++ b/frameworks/CSharp/aspnetcore/README.md
@@ -6,5 +6,5 @@ See [.NET Core](http://dot.net) and [ASP.NET Core](https://github.com/dotnet/asp
**Language**
-* C# 8.0
+* C# 13.0
diff --git a/frameworks/CSharp/aspnetcore/benchmark_config.json b/frameworks/CSharp/aspnetcore/benchmark_config.json
index 426f94ea5f7..831a9f27d81 100644
--- a/frameworks/CSharp/aspnetcore/benchmark_config.json
+++ b/frameworks/CSharp/aspnetcore/benchmark_config.json
@@ -30,6 +30,7 @@
"json_url": "/json",
"db_url": "/db",
"query_url": "/queries/",
+ "fortune_url": "/fortunes",
"update_url": "/updates/",
"cached_query_url": "/cached-worlds/",
"port": 8080,
diff --git a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
index 01ed70de876..12f3446d8b7 100644
--- a/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
+++ b/frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
index 83105ed34be..68c70002683 100644
--- a/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
+++ b/frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
@@ -9,8 +9,8 @@
-
-
+
+
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs
index eb5fff0199e..a99586c96e2 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs
@@ -6,7 +6,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private static async Task Caching(PipeWriter pipeWriter, int count)
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs
index 52a0939559c..0279754a128 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if !AOT
+using System;
using System.IO.Pipelines;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@@ -9,7 +9,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private async Task FortunesRaw(PipeWriter pipeWriter)
{
@@ -19,7 +19,7 @@ await RawDb.LoadFortunesRows(),
FortunesTemplateFactory);
}
- private ValueTask OutputFortunes(PipeWriter pipeWriter, TModel model, SliceFactory templateFactory)
+ private ValueTask OutputFortunes(PipeWriter pipeWriter, TModel model, Func> templateFactory)
{
// Render headers
var preamble = """
@@ -39,7 +39,7 @@ private ValueTask OutputFortunes(PipeWriter pipeWriter, TModel model, Sl
// Kestrel PipeWriter span size is 4K, headers above already written to first span & template output is ~1350 bytes,
// so 2K chunk size should result in only a single span and chunk being used.
var chunkedWriter = GetChunkedWriter(pipeWriter, chunkSizeHint: 2048);
- var renderTask = template.RenderAsync(chunkedWriter, null, HtmlEncoder);
+ var renderTask = template.RenderAsync(chunkedWriter, HtmlEncoder);
if (renderTask.IsCompletedSuccessfully)
{
@@ -51,18 +51,17 @@ private ValueTask OutputFortunes(PipeWriter pipeWriter, TModel model, Sl
return AwaitTemplateRenderTask(renderTask, chunkedWriter, template);
}
- private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedBufferWriter chunkedWriter, RazorSlice template)
+ private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedPipeWriter chunkedWriter, RazorSlice template)
{
await renderTask;
EndTemplateRendering(chunkedWriter, template);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void EndTemplateRendering(ChunkedBufferWriter chunkedWriter, RazorSlice template)
+ private static void EndTemplateRendering(ChunkedPipeWriter chunkedWriter, RazorSlice template)
{
- chunkedWriter.End();
+ chunkedWriter.Complete();
ReturnChunkedWriter(chunkedWriter);
template.Dispose();
}
}
-#endif
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs
index cbd375cb61b..892ecc48457 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs
@@ -12,7 +12,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication : IHttpConnection
+public sealed partial class BenchmarkApplication : IHttpConnection
{
private State _state;
@@ -193,15 +193,15 @@ private static BufferWriter GetWriter(PipeWriter pipeWriter, int
=> new(new(pipeWriter), sizeHint);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static ChunkedBufferWriter GetChunkedWriter(PipeWriter pipeWriter, int chunkSizeHint)
+ private static ChunkedPipeWriter GetChunkedWriter(PipeWriter pipeWriter, int chunkSizeHint)
{
var writer = ChunkedWriterPool.Get();
- writer.SetOutput(new WriterAdapter(pipeWriter), chunkSizeHint);
+ writer.SetOutput(pipeWriter, chunkSizeHint);
return writer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void ReturnChunkedWriter(ChunkedBufferWriter writer) => ChunkedWriterPool.Return(writer);
+ private static void ReturnChunkedWriter(ChunkedPipeWriter writer) => ChunkedWriterPool.Return(writer);
private struct WriterAdapter : IBufferWriter
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs
index 5babe2b61eb..dbfea6b0454 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs
@@ -9,7 +9,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private readonly static uint _jsonPayloadSize = (uint)JsonSerializer.SerializeToUtf8Bytes(
new JsonMessage { message = "Hello, World!" },
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs
index 0541e20de1f..82ea5a4a8a2 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs
@@ -8,7 +8,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private static async Task MultipleQueries(PipeWriter pipeWriter, int count)
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs
index 6e4c4eec1c8..57c90e64e92 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs
@@ -7,7 +7,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private static ReadOnlySpan _plaintextPreamble =>
"HTTP/1.1 200 OK\r\n"u8 +
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs
index 350eb43ad13..dd8add86fab 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs
@@ -7,7 +7,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private static async Task SingleQuery(PipeWriter pipeWriter)
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs
index 6962aa0cf2c..66bfdba1858 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs
@@ -7,7 +7,7 @@
namespace PlatformBenchmarks;
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
{
private static async Task Updates(PipeWriter pipeWriter, int count)
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs
index e256e958c75..2db511586a3 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs
@@ -10,9 +10,8 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.Extensions.ObjectPool;
-#if !AOT
+using Platform.Templates;
using RazorSlices;
-#endif
namespace PlatformBenchmarks
{
@@ -42,26 +41,24 @@ public sealed partial class BenchmarkApplication
public static RawDb RawDb { get; set; }
- private static readonly DefaultObjectPool> ChunkedWriterPool
+ private static readonly DefaultObjectPool ChunkedWriterPool
= new(new ChunkedWriterObjectPolicy());
- private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy>
+ private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy
{
- public ChunkedBufferWriter Create() => new();
+ public ChunkedPipeWriter Create() => new();
- public bool Return(ChunkedBufferWriter writer)
+ public bool Return(ChunkedPipeWriter writer)
{
writer.Reset();
return true;
}
}
-#if !AOT
#if NPGSQL
- private readonly static SliceFactory> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory>("/Templates/FortunesUtf8.cshtml");
+ private readonly static Func, RazorSlice>> FortunesTemplateFactory = FortunesUtf8.Create;
#else
- private readonly static SliceFactory> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory>("/Templates/FortunesUtf16.cshtml");
-#endif
+ private readonly static Func, RazorSlice>> FortunesTemplateFactory = FortunesUtf16.Create;
#endif
[ThreadStatic]
@@ -167,9 +164,7 @@ private bool ProcessRequest(ref BufferWriter writer)
private Task ProcessRequestAsync() => _requestType switch
{
-#if !AOT
RequestType.FortunesRaw => FortunesRaw(Writer),
-#endif
RequestType.SingleQuery => SingleQuery(Writer),
RequestType.Caching => Caching(Writer, _queries),
RequestType.Updates => Updates(Writer, _queries),
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/ChunkedBufferWriter.cs b/frameworks/CSharp/aspnetcore/src/Platform/ChunkedPipeWriter.cs
similarity index 85%
rename from frameworks/CSharp/aspnetcore/src/Platform/ChunkedBufferWriter.cs
rename to frameworks/CSharp/aspnetcore/src/Platform/ChunkedPipeWriter.cs
index 700519edb58..5a1dd80c678 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/ChunkedBufferWriter.cs
+++ b/frameworks/CSharp/aspnetcore/src/Platform/ChunkedPipeWriter.cs
@@ -5,35 +5,40 @@
using System.Buffers;
using System.Buffers.Text;
using System.Diagnostics;
+using System.IO.Pipelines;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
namespace PlatformBenchmarks;
-internal sealed class ChunkedBufferWriter : IBufferWriter where TWriter : IBufferWriter
+internal sealed class ChunkedPipeWriter : PipeWriter
{
private const int DefaultChunkSizeHint = 2048;
private static readonly StandardFormat DefaultHexFormat = GetHexFormat(DefaultChunkSizeHint);
private static ReadOnlySpan ChunkTerminator => "\r\n"u8;
- private TWriter _output;
+ private PipeWriter _output;
private int _chunkSizeHint;
private StandardFormat _hexFormat = DefaultHexFormat;
private Memory _currentFullChunk;
private Memory _currentChunk;
private int _buffered;
+ private long _unflushedBytes;
private bool _ended = false;
public Memory Memory => _currentChunk;
- public TWriter Output => _output;
+ public PipeWriter Output => _output;
public int Buffered => _buffered;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void SetOutput(TWriter output, int chunkSizeHint = DefaultChunkSizeHint)
+ public void SetOutput(PipeWriter output, int chunkSizeHint = DefaultChunkSizeHint)
{
_buffered = 0;
+ _unflushedBytes = 0;
_chunkSizeHint = chunkSizeHint;
_output = output;
@@ -44,6 +49,7 @@ public void SetOutput(TWriter output, int chunkSizeHint = DefaultChunkSizeHint)
public void Reset()
{
_buffered = 0;
+ _unflushedBytes = 0;
_output = default;
_ended = false;
_hexFormat = DefaultHexFormat;
@@ -51,16 +57,21 @@ public void Reset()
_currentChunk = default;
}
+ public override bool CanGetUnflushedBytes => true;
+
+ public override long UnflushedBytes => _unflushedBytes;
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Advance(int count)
+ public override void Advance(int count)
{
ThrowIfEnded();
_buffered += count;
+ _unflushedBytes += count;
_currentChunk = _currentChunk[count..];
}
- public Memory GetMemory(int sizeHint = 0)
+ public override Memory GetMemory(int sizeHint = 0)
{
ThrowIfEnded();
@@ -71,9 +82,14 @@ public Memory GetMemory(int sizeHint = 0)
return _currentChunk;
}
- public Span GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;
+ public override Span GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;
+
+ public override void CancelPendingFlush()
+ {
+ _output.CancelPendingFlush();
+ }
- public void End()
+ public override void Complete(Exception exception = null)
{
ThrowIfEnded();
@@ -82,6 +98,17 @@ public void End()
_ended = true;
}
+ public override ValueTask FlushAsync(CancellationToken cancellationToken = default)
+ {
+ CommitCurrentChunk(isFinal: false);
+
+ var flushTask = _output.FlushAsync(cancellationToken);
+
+ _unflushedBytes = 0;
+
+ return flushTask;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static StandardFormat GetHexFormat(int maxValue)
{
diff --git a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
index fa716bda4c7..7db51dc3ec7 100644
--- a/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
+++ b/frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
@@ -6,7 +6,6 @@
true
preview
38063504-d08c-495a-89c9-daaad2f60f31
- AOT;$(DefineConstants)
@@ -19,15 +18,12 @@
-
+
-
+
-
- $(MSBuildThisFileDirectory)Templates/**;$(DefaultItemExcludes)
-