Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion frameworks/CSharp/aspnetcore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

1 change: 1 addition & 0 deletions frameworks/CSharp/aspnetcore/benchmark_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Npgsql" Version="8.0.5" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="RazorSlices" Version="0.8.1" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Npgsql" Version="8.0.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-rc.2" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private static async Task Caching(PipeWriter pipeWriter, int count)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// 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;
using RazorSlices;

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private async Task FortunesRaw(PipeWriter pipeWriter)
{
Expand All @@ -19,7 +19,7 @@ await RawDb.LoadFortunesRows(),
FortunesTemplateFactory);
}

private ValueTask OutputFortunes<TModel>(PipeWriter pipeWriter, TModel model, SliceFactory<TModel> templateFactory)
private ValueTask OutputFortunes<TModel>(PipeWriter pipeWriter, TModel model, Func<TModel, RazorSlice<TModel>> templateFactory)
{
// Render headers
var preamble = """
Expand All @@ -39,7 +39,7 @@ private ValueTask OutputFortunes<TModel>(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)
{
Expand All @@ -51,18 +51,17 @@ private ValueTask OutputFortunes<TModel>(PipeWriter pipeWriter, TModel model, Sl
return AwaitTemplateRenderTask(renderTask, chunkedWriter, template);
}

private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedBufferWriter<WriterAdapter> 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<WriterAdapter> chunkedWriter, RazorSlice template)
private static void EndTemplateRendering(ChunkedPipeWriter chunkedWriter, RazorSlice template)
{
chunkedWriter.End();
chunkedWriter.Complete();
ReturnChunkedWriter(chunkedWriter);
template.Dispose();
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication : IHttpConnection
public sealed partial class BenchmarkApplication : IHttpConnection
{
private State _state;

Expand Down Expand Up @@ -193,15 +193,15 @@ private static BufferWriter<WriterAdapter> GetWriter(PipeWriter pipeWriter, int
=> new(new(pipeWriter), sizeHint);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ChunkedBufferWriter<WriterAdapter> 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<WriterAdapter> writer) => ChunkedWriterPool.Return(writer);
private static void ReturnChunkedWriter(ChunkedPipeWriter writer) => ChunkedWriterPool.Return(writer);

private struct WriterAdapter : IBufferWriter<byte>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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!" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private static async Task MultipleQueries(PipeWriter pipeWriter, int count)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private static ReadOnlySpan<byte> _plaintextPreamble =>
"HTTP/1.1 200 OK\r\n"u8 +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private static async Task SingleQuery(PipeWriter pipeWriter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace PlatformBenchmarks;

public partial class BenchmarkApplication
public sealed partial class BenchmarkApplication
{
private static async Task Updates(PipeWriter pipeWriter, int count)
{
Expand Down
19 changes: 7 additions & 12 deletions frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -42,26 +41,24 @@ public sealed partial class BenchmarkApplication

public static RawDb RawDb { get; set; }

private static readonly DefaultObjectPool<ChunkedBufferWriter<WriterAdapter>> ChunkedWriterPool
private static readonly DefaultObjectPool<ChunkedPipeWriter> ChunkedWriterPool
= new(new ChunkedWriterObjectPolicy());

private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy<ChunkedBufferWriter<WriterAdapter>>
private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy<ChunkedPipeWriter>
{
public ChunkedBufferWriter<WriterAdapter> Create() => new();
public ChunkedPipeWriter Create() => new();

public bool Return(ChunkedBufferWriter<WriterAdapter> writer)
public bool Return(ChunkedPipeWriter writer)
{
writer.Reset();
return true;
}
}

#if !AOT
#if NPGSQL
private readonly static SliceFactory<List<FortuneUtf8>> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory<List<FortuneUtf8>>("/Templates/FortunesUtf8.cshtml");
private readonly static Func<List<FortuneUtf8>, RazorSlice<List<FortuneUtf8>>> FortunesTemplateFactory = FortunesUtf8.Create;
#else
private readonly static SliceFactory<List<FortuneUtf16>> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory<List<FortuneUtf16>>("/Templates/FortunesUtf16.cshtml");
#endif
private readonly static Func<List<FortuneUtf16>, RazorSlice<List<FortuneUtf16>>> FortunesTemplateFactory = FortunesUtf16.Create;
#endif

[ThreadStatic]
Expand Down Expand Up @@ -167,9 +164,7 @@ private bool ProcessRequest(ref BufferWriter<WriterAdapter> 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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TWriter> : IBufferWriter<byte> where TWriter : IBufferWriter<byte>
internal sealed class ChunkedPipeWriter : PipeWriter
{
private const int DefaultChunkSizeHint = 2048;
private static readonly StandardFormat DefaultHexFormat = GetHexFormat(DefaultChunkSizeHint);
private static ReadOnlySpan<byte> ChunkTerminator => "\r\n"u8;

private TWriter _output;
private PipeWriter _output;
private int _chunkSizeHint;
private StandardFormat _hexFormat = DefaultHexFormat;
private Memory<byte> _currentFullChunk;
private Memory<byte> _currentChunk;
private int _buffered;
private long _unflushedBytes;
private bool _ended = false;

public Memory<byte> 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;

Expand All @@ -44,23 +49,29 @@ public void SetOutput(TWriter output, int chunkSizeHint = DefaultChunkSizeHint)
public void Reset()
{
_buffered = 0;
_unflushedBytes = 0;
_output = default;
_ended = false;
_hexFormat = DefaultHexFormat;
_currentFullChunk = default;
_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<byte> GetMemory(int sizeHint = 0)
public override Memory<byte> GetMemory(int sizeHint = 0)
{
ThrowIfEnded();

Expand All @@ -71,9 +82,14 @@ public Memory<byte> GetMemory(int sizeHint = 0)
return _currentChunk;
}

public Span<byte> GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;
public override Span<byte> GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;

public override void CancelPendingFlush()
{
_output.CancelPendingFlush();
}

public void End()
public override void Complete(Exception exception = null)
{
ThrowIfEnded();

Expand All @@ -82,6 +98,17 @@ public void End()
_ended = true;
}

public override ValueTask<FlushResult> 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)
{
Expand Down
8 changes: 2 additions & 6 deletions frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<IsTestAssetProject>true</IsTestAssetProject>
<LangVersion>preview</LangVersion>
<UserSecretsId>38063504-d08c-495a-89c9-daaad2f60f31</UserSecretsId>
<DefineConstants Condition="'$(PublishAot)' == 'true'">AOT;$(DefineConstants)</DefineConstants>
</PropertyGroup>

<PropertyGroup>
Expand All @@ -19,15 +18,12 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Npgsql" Version="8.0.5" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="MySqlConnector" Version="2.3.7" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="RazorSlices" Version="0.7.0" Condition="$(PublishAot) != 'true'" />
<PackageReference Include="RazorSlices" Version="0.8.1" />
</ItemGroup>

<PropertyGroup Condition="$(PublishAot) == 'true'">
<DefaultItemExcludes>$(MSBuildThisFileDirectory)Templates/**;$(DefaultItemExcludes)</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup Condition="$(PublishAot) == 'true'">
<RuntimeHostConfigurationOption Include="System.Threading.ThreadPool.HillClimbing.Disable" Value="true" />
</ItemGroup>
Expand Down
Loading