diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.csproj b/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.csproj deleted file mode 100644 index c138ffc0604..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - net7.0 - Exe - enable - true - - - - - - - - - - - - - - - - - diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.sln b/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.sln deleted file mode 100644 index 3c1db8ccf6d..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Benchmarks.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26507.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks.csproj", "{8D5521DB-5F71-4F26-9E60-92A158E1F50E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8D5521DB-5F71-4F26-9E60-92A158E1F50E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D5521DB-5F71-4F26-9E60-92A158E1F50E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D5521DB-5F71-4F26-9E60-92A158E1F50E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D5521DB-5F71-4F26-9E60-92A158E1F50E}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/AppSettings.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/AppSettings.cs deleted file mode 100644 index 6d4533306d0..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/AppSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -namespace Benchmarks.Configuration; - -public class AppSettings -{ - public string ConnectionString { get; set; } - - public DatabaseServer Database { get; set; } = DatabaseServer.None; -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleArgs.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleArgs.cs deleted file mode 100644 index 453a594db71..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleArgs.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -namespace Benchmarks.Configuration; - -public class ConsoleArgs -{ - public ConsoleArgs(string[] args) - { - Args = args; - } - - public string[] Args { get; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleHostScenariosConfiguration.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleHostScenariosConfiguration.cs deleted file mode 100644 index 4001f94fea2..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/ConsoleHostScenariosConfiguration.cs +++ /dev/null @@ -1,79 +0,0 @@ -// 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. - -namespace Benchmarks.Configuration; - -public class ConsoleHostScenariosConfiguration : IScenariosConfiguration -{ - private readonly string[] _args; - - public ConsoleHostScenariosConfiguration(ConsoleArgs args) - { - _args = args.Args; - } - - public void ConfigureScenarios(Scenarios scenarios) - { - var scenarioConfig = new ConfigurationBuilder() - .AddJsonFile("scenarios.json", optional: true) - .AddCommandLine(_args) - .Build(); - - var enabledCount = 0; - var configuredScenarios = scenarioConfig["scenarios"]; - if (!string.IsNullOrWhiteSpace(configuredScenarios)) - { - Console.WriteLine("Scenario configuration found in scenarios.json and/or command line args"); - var choices = configuredScenarios.Split(','); - foreach (var choice in choices) - { - enabledCount += scenarios.Enable(choice); - } - } - else - { - Console.WriteLine("Which scenarios would you like to enable?:"); - Console.WriteLine(); - foreach (var scenario in Scenarios.GetNames()) - { - Console.WriteLine(" " + scenario); - } - Console.WriteLine(); - Console.WriteLine("Type full or partial scenario names separated by commas and hit [Enter]"); - Console.Write("> "); - - var choices = Console.ReadLine().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - if (choices.Length > 0) - { - foreach (var choice in choices) - { - enabledCount += scenarios.Enable(choice); - } - } - } - - if (enabledCount == 0) - { - Console.WriteLine(); - Console.WriteLine("No matching scenarios found, enabling defaults"); - scenarios.EnableDefault(); - } - - PrintEnabledScenarios(scenarios.GetEnabled()); - } - - private static void PrintEnabledScenarios(IEnumerable scenarios) - { - Console.WriteLine(); - Console.WriteLine("The following scenarios were enabled:"); - - var maxNameLength = scenarios.Max(s => s.Name.Length); - - foreach (var scenario in scenarios) - { - Console.WriteLine($" {scenario.Name.PadRight(maxNameLength)} -> {string.Join($"{Environment.NewLine}{"".PadLeft(maxNameLength + 6)}", scenario.Paths)}"); - } - Console.WriteLine(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/DatabaseServer.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/DatabaseServer.cs deleted file mode 100644 index cc17a2b0910..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/DatabaseServer.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - - -namespace Benchmarks.Configuration; - -public enum DatabaseServer -{ - None, - SqlServer, - PostgreSql, - MySql -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/EnabledScenario.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/EnabledScenario.cs deleted file mode 100644 index 1042576b79d..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/EnabledScenario.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -namespace Benchmarks.Configuration; - -public class EnabledScenario -{ - public EnabledScenario(string name, IEnumerable paths) - { - Name = name; - Paths = paths; - } - - public string Name { get; } - - public IEnumerable Paths { get; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/IScenariosConfiguration.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/IScenariosConfiguration.cs deleted file mode 100644 index f66ea8d3b57..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/IScenariosConfiguration.cs +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -namespace Benchmarks.Configuration; - -public interface IScenariosConfiguration -{ - void ConfigureScenarios(Scenarios scenarios); -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/Scenarios.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/Scenarios.cs deleted file mode 100644 index 3381bcc29e3..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Configuration/Scenarios.cs +++ /dev/null @@ -1,163 +0,0 @@ -// 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. - -using System.Linq.Expressions; -using System.Reflection; -using Microsoft.EntityFrameworkCore.Infrastructure; - -namespace Benchmarks.Configuration; - -public class Scenarios -{ - public Scenarios(IScenariosConfiguration scenariosConfiguration) - { - scenariosConfiguration.ConfigureScenarios(this); - } - - [ScenarioPath("/plaintext")] - public bool Plaintext { get; set; } - - [ScenarioPath("/json")] - public bool Json { get; set; } - - [ScenarioPath("/128B.txt", "/512B.txt", "/1KB.txt", "/4KB.txt", "/16KB.txt", "/512KB.txt", "/1MB.txt", "/5MB.txt")] - public bool StaticFiles { get; set; } - - [ScenarioPath("/db/raw")] - public bool DbSingleQueryRaw { get; set; } - - [ScenarioPath("/db/ef")] - public bool DbSingleQueryEf { get; set; } - - [ScenarioPath("/db/dapper")] - public bool DbSingleQueryDapper { get; set; } - - [ScenarioPath("/queries/raw")] - public bool DbMultiQueryRaw { get; set; } - - [ScenarioPath("/queries/ef")] - public bool DbMultiQueryEf { get; set; } - - [ScenarioPath("/queries/dapper")] - public bool DbMultiQueryDapper { get; set; } - - [ScenarioPath("/updates/raw")] - public bool DbMultiUpdateRaw { get; set; } - - [ScenarioPath("/updates/ef")] - public bool DbMultiUpdateEf { get; set; } - - [ScenarioPath("/updates/dapper")] - public bool DbMultiUpdateDapper { get; set; } - - [ScenarioPath("/fortunes/raw")] - public bool DbFortunesRaw { get; set; } - - [ScenarioPath("/fortunes/ef")] - public bool DbFortunesEf { get; set; } - - [ScenarioPath("/fortunes/dapper")] - public bool DbFortunesDapper { get; set; } - - [ScenarioPath("/mvc/plaintext")] - public bool MvcPlaintext { get; set; } - - [ScenarioPath("/mvc/json")] - public bool MvcJson { get; set; } - - [ScenarioPath("/mvc/view")] - public bool MvcViews { get; set; } - - [ScenarioPath("/mvc/db/raw")] - public bool MvcDbSingleQueryRaw { get; set; } - - [ScenarioPath("/mvc/db/dapper")] - public bool MvcDbSingleQueryDapper { get; set; } - - [ScenarioPath("/mvc/db/ef")] - public bool MvcDbSingleQueryEf { get; set; } - - [ScenarioPath("/mvc/queries/raw")] - public bool MvcDbMultiQueryRaw { get; set; } - - [ScenarioPath("/mvc/queries/dapper")] - public bool MvcDbMultiQueryDapper { get; set; } - - [ScenarioPath("/mvc/queries/ef")] - public bool MvcDbMultiQueryEf { get; set; } - - [ScenarioPath("/mvc/updates/raw")] - public bool MvcDbMultiUpdateRaw { get; set; } - - [ScenarioPath("/mvc/updates/dapper")] - public bool MvcDbMultiUpdateDapper { get; set; } - - [ScenarioPath("/mvc/updates/ef")] - public bool MvcDbMultiUpdateEf { get; set; } - - [ScenarioPath("/mvc/fortunes/raw")] - public bool MvcDbFortunesRaw { get; set; } - - [ScenarioPath("/mvc/fortunes/ef")] - public bool MvcDbFortunesEf { get; set; } - - [ScenarioPath("/mvc/fortunes/dapper")] - public bool MvcDbFortunesDapper { get; set; } - - public bool Any(string partialName) => - typeof(Scenarios).GetTypeInfo().DeclaredProperties - .Where(p => p.Name.IndexOf(partialName, StringComparison.Ordinal) >= 0 && (bool)p.GetValue(this)) - .Any(); - - public IEnumerable GetEnabled() => - typeof(Scenarios).GetTypeInfo().DeclaredProperties - .Where(p => p.GetValue(this) is bool && (bool)p.GetValue(this)) - .Select(p => new EnabledScenario(p.Name, p.GetCustomAttribute()?.Paths)); - - public static IEnumerable GetNames() => - typeof(Scenarios).GetTypeInfo().DeclaredProperties - .Select(p => p.Name); - - public static string[] GetPaths(Expression> scenarioExpression) => - scenarioExpression.GetPropertyAccess().GetCustomAttribute().Paths; - - public static string GetPath(Expression> scenarioExpression) => - GetPaths(scenarioExpression)[0]; - - public int Enable(string partialName) - { - if (string.Equals(partialName, "[default]", StringComparison.OrdinalIgnoreCase)) - { - EnableDefault(); - return 2; - } - - var props = typeof(Scenarios).GetTypeInfo().DeclaredProperties - .Where(p => string.Equals(partialName, "[all]", StringComparison.OrdinalIgnoreCase) || p.Name.StartsWith(partialName, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - foreach (var p in props) - { - p.SetValue(this, true); - } - - return props.Count; - } - - public void EnableDefault() - { - Plaintext = true; - Json = true; - } -} - -[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)] -public sealed class ScenarioPathAttribute : Attribute -{ - public ScenarioPathAttribute(params string[] paths) - { - Paths = paths; - } - - public string[] Paths { get; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/FortunesController.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/FortunesController.cs deleted file mode 100644 index 1c3f228b197..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/FortunesController.cs +++ /dev/null @@ -1,32 +0,0 @@ -// 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. - -using Benchmarks.Data; -using Microsoft.AspNetCore.Mvc; - -namespace Benchmarks.Controllers; - -[Route("mvc/fortunes")] -public class FortunesController : Controller -{ - [HttpGet("raw")] - public async Task Raw() - { - var db = HttpContext.RequestServices.GetRequiredService(); - return View("Fortunes", await db.LoadFortunesRows()); - } - - [HttpGet("dapper")] - public async Task Dapper() - { - var db = HttpContext.RequestServices.GetRequiredService(); - return View("Fortunes", await db.LoadFortunesRows()); - } - - [HttpGet("ef")] - public async Task Ef() - { - var db = HttpContext.RequestServices.GetRequiredService(); - return View("Fortunes", await db.LoadFortunesRows()); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/HomeController.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/HomeController.cs deleted file mode 100644 index 9250ea7aa55..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/HomeController.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -using System.Text; -using Microsoft.AspNetCore.Mvc; - -namespace Benchmarks.Controllers; - -[Route("mvc")] -public class HomeController : Controller -{ - [HttpGet("plaintext")] - public IActionResult Plaintext() - { - return new PlainTextActionResult(); - } - - [HttpGet("json")] - [Produces("application/json")] - public object Json() - { - return new { message = "Hello, World!" }; - } - - [HttpGet("view")] - public ViewResult Index() - { - return View(); - } - - private class PlainTextActionResult : IActionResult - { - private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); - - public Task ExecuteResultAsync(ActionContext context) - { - var response = context.HttpContext.Response; - response.StatusCode = StatusCodes.Status200OK; - response.ContentType = "text/plain"; - var payloadLength = _helloWorldPayload.Length; - response.ContentLength = payloadLength; - return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleQueriesController.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleQueriesController.cs deleted file mode 100644 index 15a8f1c1b8c..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleQueriesController.cs +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -using Benchmarks.Data; -using Microsoft.AspNetCore.Mvc; - -namespace Benchmarks.Controllers; - -[Route("mvc/queries")] -public class MultipleQueriesController : Controller -{ - [HttpGet("raw")] - [Produces("application/json")] - public Task Raw(int queries = 1) - { - return ExecuteQuery(queries); - } - - [HttpGet("dapper")] - [Produces("application/json")] - public Task Dapper(int queries = 1) - { - return ExecuteQuery(queries); - } - - [HttpGet("ef")] - [Produces("application/json")] - public Task Ef(int queries = 1) - { - return ExecuteQuery(queries); - } - - private Task ExecuteQuery(int queries) where T : IDb - { - queries = queries < 1 ? 1 : queries > 500 ? 500 : queries; - var db = HttpContext.RequestServices.GetRequiredService(); - return db.LoadMultipleQueriesRows(queries); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleUpdatesController.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleUpdatesController.cs deleted file mode 100644 index 578e7bab1cf..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/MultipleUpdatesController.cs +++ /dev/null @@ -1,39 +0,0 @@ -// 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. - -using Benchmarks.Data; -using Microsoft.AspNetCore.Mvc; - -namespace Benchmarks.Controllers; - -[Route("mvc/updates")] -public class MultipleUpdatesController : Controller -{ - [HttpGet("raw")] - [Produces("application/json")] - public Task Raw(int queries = 1) - { - return ExecuteQuery(queries); - } - - [HttpGet("dapper")] - [Produces("application/json")] - public Task Dapper(int queries = 1) - { - return ExecuteQuery(queries); - } - - [HttpGet("ef")] - [Produces("application/json")] - public Task Ef(int queries = 1) - { - return ExecuteQuery(queries); - } - - private Task ExecuteQuery(int queries) where T : IDb - { - queries = queries < 1 ? 1 : queries > 500 ? 500 : queries; - var db = HttpContext.RequestServices.GetRequiredService(); - return db.LoadMultipleUpdatesRows(queries); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/SingleQueryController.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/SingleQueryController.cs deleted file mode 100644 index 7099c89feec..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Controllers/SingleQueryController.cs +++ /dev/null @@ -1,38 +0,0 @@ -// 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. - -using Benchmarks.Data; -using Microsoft.AspNetCore.Mvc; - -namespace Benchmarks.Controllers; - -[Route("mvc/db")] -public class SingleQueryController : Controller -{ - [HttpGet("raw")] - [Produces("application/json")] - public Task Raw() - { - return ExecuteQuery(); - } - - [HttpGet("dapper")] - [Produces("application/json")] - public Task Dapper() - { - return ExecuteQuery(); - } - - [HttpGet("ef")] - [Produces("application/json")] - public Task Ef() - { - return ExecuteQuery(); - } - - private Task ExecuteQuery() where T : IDb - { - var db = HttpContext.RequestServices.GetRequiredService(); - return db.LoadSingleQueryRow(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/ApplicationDbContext.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/ApplicationDbContext.cs deleted file mode 100644 index 3ca3b52b2c3..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/ApplicationDbContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -using Microsoft.EntityFrameworkCore; - -namespace Benchmarks.Data; - -public sealed class ApplicationDbContext : DbContext -{ - public ApplicationDbContext(DbContextOptions options) - : base(options) - { - ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - ChangeTracker.AutoDetectChangesEnabled = false; - } - - public DbSet World { get; set; } - - public DbSet Fortune { get; set; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/BatchUpdateString.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/BatchUpdateString.cs deleted file mode 100644 index d4680bdf961..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/BatchUpdateString.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -using Benchmarks.Configuration; - -namespace Benchmarks.Data; - -internal class BatchUpdateString -{ - private const int MaxBatch = 500; - - private static readonly string[] _queries = new string[MaxBatch + 1]; - - public static DatabaseServer DatabaseServer; - - public static string Query(int batchSize) - { - if (_queries[batchSize] != null) - { - return _queries[batchSize]; - } - - var lastIndex = batchSize - 1; - - var sb = StringBuilderCache.Acquire(); - - if (DatabaseServer == DatabaseServer.PostgreSql) - { - sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES "); - Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@Id_{i}, @Random_{i}), ")); - sb.Append($"(@Id_{lastIndex}, @Random_{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id"); - } - else - { - Enumerable.Range(0, batchSize).ToList().ForEach(i => sb.Append($"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};")); - } - - return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/DapperDb.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/DapperDb.cs deleted file mode 100644 index 654efb00b86..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/DapperDb.cs +++ /dev/null @@ -1,107 +0,0 @@ -// 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. - -using System.Data.Common; -using System.Dynamic; -using Benchmarks.Configuration; -using Dapper; -using Microsoft.Extensions.Options; - -namespace Benchmarks.Data; - -public class DapperDb : IDb -{ - private static readonly Comparison WorldSortComparison = (a, b) => a.Id.CompareTo(b.Id); - - private readonly IRandom _random; - private readonly DbProviderFactory _dbProviderFactory; - private readonly string _connectionString; - - public DapperDb(IRandom random, DbProviderFactory dbProviderFactory, IOptions appSettings) - { - _random = random; - _dbProviderFactory = dbProviderFactory; - _connectionString = appSettings.Value.ConnectionString; - } - - public async Task LoadSingleQueryRow() - { - using var db = _dbProviderFactory.CreateConnection(); - db.ConnectionString = _connectionString; - - // Note: Don't need to open connection if only doing one thing; let dapper do it - return await ReadSingleRow(db); - } - - Task ReadSingleRow(DbConnection db) - { - return db.QueryFirstOrDefaultAsync( - "SELECT id, randomnumber FROM world WHERE id = @Id", - new { Id = _random.Next(1, 10001) }); - } - - public async Task LoadMultipleQueriesRows(int count) - { - var results = new World[count]; - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - await db.OpenAsync(); - - for (int i = 0; i < count; i++) - { - results[i] = await ReadSingleRow(db); - } - } - - return results; - } - - public async Task LoadMultipleUpdatesRows(int count) - { - IDictionary parameters = new ExpandoObject(); - - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - await db.OpenAsync(); - - var results = new World[count]; - for (int i = 0; i < count; i++) - { - results[i] = await ReadSingleRow(db); - } - - for (int i = 0; i < count; i++) - { - var randomNumber = _random.Next(1, 10001); - parameters[$"@Random_{i}"] = randomNumber; - parameters[$"@Id_{i}"] = results[i].Id; - - results[i].RandomNumber = randomNumber; - } - - await db.ExecuteAsync(BatchUpdateString.Query(count), parameters); - return results; - } - - } - - public async Task> LoadFortunesRows() - { - List result; - - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - - // Note: don't need to open connection if only doing one thing; let dapper do it - result = (await db.QueryAsync("SELECT id, message FROM fortune")).AsList(); - } - - result.Add(new Fortune { Message = "Additional fortune added at request time." }); - result.Sort(); - - return result; - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/EfDb.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/EfDb.cs deleted file mode 100644 index 37a64fbd1c9..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/EfDb.cs +++ /dev/null @@ -1,92 +0,0 @@ -// 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. - -using Benchmarks.Configuration; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; - -namespace Benchmarks.Data; - -public class EfDb : IDb -{ - private readonly IRandom _random; - private readonly ApplicationDbContext _dbContext; - - public EfDb(IRandom random, ApplicationDbContext dbContext, IOptions appSettings) - { - _random = random; - _dbContext = dbContext; - } - - private static readonly Func> _firstWorldQuery - = EF.CompileAsyncQuery((ApplicationDbContext context, int id) - => context.World.First(w => w.Id == id)); - - public Task LoadSingleQueryRow() - { - var id = _random.Next(1, 10001); - - return _firstWorldQuery(_dbContext, id); - } - - public async Task LoadMultipleQueriesRows(int count) - { - var result = new World[count]; - - for (var i = 0; i < count; i++) - { - var id = _random.Next(1, 10001); - - result[i] = await _firstWorldQuery(_dbContext, id); - } - - return result; - } - - private static readonly Func> _firstWorldTrackedQuery - = EF.CompileAsyncQuery((ApplicationDbContext context, int id) - => context.World.AsTracking().First(w => w.Id == id)); - - public async Task LoadMultipleUpdatesRows(int count) - { - var results = new World[count]; - var usedIds = new HashSet(count); - - for (var i = 0; i < count; i++) - { - int id; - do - { - id = _random.Next(1, 10001); - } while (!usedIds.Add(id)); - - results[i] = await _firstWorldTrackedQuery(_dbContext, id); - - results[i].RandomNumber = _random.Next(1, 10001); - - _dbContext.Entry(results[i]).State = EntityState.Modified; - } - - await _dbContext.SaveChangesAsync(); - - return results; - } - - private static readonly Func> _fortunesQuery - = EF.CompileAsyncQuery((ApplicationDbContext context) => context.Fortune); - - public async Task> LoadFortunesRows() - { - var result = new List(); - - await foreach (var element in _fortunesQuery(_dbContext)) - { - result.Add(element); - } - - result.Add(new Fortune { Message = "Additional fortune added at request time." }); - result.Sort(); - - return result; - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/Fortune.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/Fortune.cs deleted file mode 100644 index b267b3391b8..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/Fortune.cs +++ /dev/null @@ -1,30 +0,0 @@ -// 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. - -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - -namespace Benchmarks.Data; - -[Table("fortune")] -public class Fortune : IComparable, IComparable -{ - [Column("id")] - public int Id { get; set; } - - [Column("message")] - [StringLength(2048)] - [Required] - public string Message { get; set; } - - public int CompareTo(object obj) - { - return CompareTo((Fortune)obj); - } - - public int CompareTo(Fortune other) - { - // Performance critical, using culture insensitive comparison - return String.CompareOrdinal(Message, other.Message); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/IDb.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/IDb.cs deleted file mode 100644 index 330bbdbb156..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/IDb.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -namespace Benchmarks.Data; - -public interface IDb -{ - Task LoadSingleQueryRow(); - - Task LoadMultipleQueriesRows(int count); - - Task LoadMultipleUpdatesRows(int count); - - Task> LoadFortunesRows(); -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/IRandom.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/IRandom.cs deleted file mode 100644 index cef51325aa9..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/IRandom.cs +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -namespace Benchmarks.Data; - -public interface IRandom -{ - int Next(int minValue, int maxValue); -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/Random.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/Random.cs deleted file mode 100644 index a2abaa87aa7..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/Random.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -using System.Runtime.CompilerServices; - -namespace Benchmarks.Data; - -public class DefaultRandom : IRandom -{ - private static int nextSeed = 0; - - // Random isn't thread safe - [ThreadStatic] - private static Random _random; - - private static Random Random => _random ?? CreateRandom(); - - [MethodImpl(MethodImplOptions.NoInlining)] - private static Random CreateRandom() - { - _random = new Random(Interlocked.Increment(ref nextSeed)); - return _random; - } - - public int Next(int minValue, int maxValue) - { - return Random.Next(minValue, maxValue); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/RawDb.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/RawDb.cs deleted file mode 100644 index a95b555d265..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/RawDb.cs +++ /dev/null @@ -1,153 +0,0 @@ -// 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. - -using System.Data; -using System.Data.Common; -using Benchmarks.Configuration; -using Microsoft.Extensions.Options; - -namespace Benchmarks.Data; - -public class RawDb : IDb -{ - private static readonly Comparison WorldSortComparison = (a, b) => a.Id.CompareTo(b.Id); - - private readonly IRandom _random; - private readonly DbProviderFactory _dbProviderFactory; - private readonly string _connectionString; - - public RawDb(IRandom random, DbProviderFactory dbProviderFactory, IOptions appSettings) - { - _random = random; - _dbProviderFactory = dbProviderFactory; - _connectionString = appSettings.Value.ConnectionString; - } - - public async Task LoadSingleQueryRow() - { - using var db = _dbProviderFactory.CreateConnection(); - db.ConnectionString = _connectionString; - await db.OpenAsync(); - - using var cmd = CreateReadCommand(db); - return await ReadSingleRow(db, cmd); - } - - async Task ReadSingleRow(DbConnection connection, DbCommand cmd) - { - using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow)) - { - await rdr.ReadAsync(); - - return new World - { - Id = rdr.GetInt32(0), - RandomNumber = rdr.GetInt32(1) - }; - } - } - - DbCommand CreateReadCommand(DbConnection connection) - { - var cmd = connection.CreateCommand(); - cmd.CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id"; - var id = cmd.CreateParameter(); - id.ParameterName = "@Id"; - id.DbType = DbType.Int32; - id.Value = _random.Next(1, 10001); - cmd.Parameters.Add(id); - - (cmd as MySqlConnector.MySqlCommand)?.Prepare(); - - return cmd; - } - - public async Task LoadMultipleQueriesRows(int count) - { - var result = new World[count]; - - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - await db.OpenAsync(); - using var cmd = CreateReadCommand(db); - for (int i = 0; i < count; i++) - { - result[i] = await ReadSingleRow(db, cmd); - cmd.Parameters["@Id"].Value = _random.Next(1, 10001); - } - } - - return result; - } - - public async Task LoadMultipleUpdatesRows(int count) - { - using var db = _dbProviderFactory.CreateConnection(); - db.ConnectionString = _connectionString; - await db.OpenAsync(); - - using var updateCmd = db.CreateCommand(); - using var queryCmd = CreateReadCommand(db); - var results = new World[count]; - for (int i = 0; i < count; i++) - { - results[i] = await ReadSingleRow(db, queryCmd); - queryCmd.Parameters["@Id"].Value = _random.Next(1, 10001); - } - - updateCmd.CommandText = BatchUpdateString.Query(count); - - for (int i = 0; i < count; i++) - { - var id = updateCmd.CreateParameter(); - id.ParameterName = $"@Id_{i}"; - id.DbType = DbType.Int32; - updateCmd.Parameters.Add(id); - - var random = updateCmd.CreateParameter(); - random.ParameterName = $"@Random_{i}"; - random.DbType = DbType.Int32; - updateCmd.Parameters.Add(random); - - var randomNumber = _random.Next(1, 10001); - id.Value = results[i].Id; - random.Value = randomNumber; - results[i].RandomNumber = randomNumber; - } - - await updateCmd.ExecuteNonQueryAsync(); - return results; - } - - public async Task> LoadFortunesRows() - { - var result = new List(); - - using (var db = _dbProviderFactory.CreateConnection()) - using (var cmd = db.CreateCommand()) - { - cmd.CommandText = "SELECT id, message FROM fortune"; - - db.ConnectionString = _connectionString; - await db.OpenAsync(); - - (cmd as MySqlConnector.MySqlCommand)?.Prepare(); - - using var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection); - while (await rdr.ReadAsync()) - { - result.Add(new Fortune - { - Id = rdr.GetInt32(0), - Message = rdr.GetString(1) - }); - } - } - - result.Add(new Fortune { Message = "Additional fortune added at request time." }); - result.Sort(); - - return result; - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/StringBuilderCache.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/StringBuilderCache.cs deleted file mode 100644 index cc2f05e0219..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/StringBuilderCache.cs +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -using System.Text; - -namespace Benchmarks.Data; - -internal static class StringBuilderCache -{ - private const int DefaultCapacity = 1386; - private const int MaxBuilderSize = DefaultCapacity * 3; - - [ThreadStatic] - private static StringBuilder t_cachedInstance; - - /// Get a StringBuilder for the specified capacity. - /// If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied. - public static StringBuilder Acquire(int capacity = DefaultCapacity) - { - if (capacity <= MaxBuilderSize) - { - StringBuilder sb = t_cachedInstance; - if (capacity < DefaultCapacity) - { - capacity = DefaultCapacity; - } - - if (sb != null) - { - // Avoid stringbuilder block fragmentation by getting a new StringBuilder - // when the requested size is larger than the current capacity - if (capacity <= sb.Capacity) - { - t_cachedInstance = null; - sb.Clear(); - return sb; - } - } - } - return new StringBuilder(capacity); - } - - public static void Release(StringBuilder sb) - { - if (sb.Capacity <= MaxBuilderSize) - { - t_cachedInstance = sb; - } - } - - public static string GetStringAndRelease(StringBuilder sb) - { - string result = sb.ToString(); - Release(sb); - return result; - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Data/World.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Data/World.cs deleted file mode 100644 index bdb515f6f2c..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Data/World.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -using System.ComponentModel.DataAnnotations.Schema; - -namespace Benchmarks.Data; - -[Table("world")] -public class World -{ - [Column("id")] - public int Id { get; set; } - - [Column("randomnumber")] - public int RandomNumber { get; set; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesDapperMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesDapperMiddleware.cs deleted file mode 100644 index 404ecdd8054..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesDapperMiddleware.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -using System.Text.Encodings.Web; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class FortunesDapperMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbFortunesDapper)); - - private readonly RequestDelegate _next; - private readonly HtmlEncoder _htmlEncoder; - - public FortunesDapperMiddleware(RequestDelegate next, HtmlEncoder htmlEncoder) - { - _next = next; - _htmlEncoder = htmlEncoder; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadFortunesRows(); - - await MiddlewareHelpers.RenderFortunesHtml(rows, httpContext, _htmlEncoder); - - return; - } - - await _next(httpContext); - } -} - -public static class FortunesDapperMiddlewareExtensions -{ - public static IApplicationBuilder UseFortunesDapper(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesEfMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesEfMiddleware.cs deleted file mode 100644 index f1f02e2660a..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesEfMiddleware.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -using System.Text.Encodings.Web; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class FortunesEfMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbFortunesEf)); - - private readonly RequestDelegate _next; - private readonly HtmlEncoder _htmlEncoder; - - public FortunesEfMiddleware(RequestDelegate next, HtmlEncoder htmlEncoder) - { - _next = next; - _htmlEncoder = htmlEncoder; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadFortunesRows(); - - await MiddlewareHelpers.RenderFortunesHtml(rows, httpContext, _htmlEncoder); - - return; - } - - await _next(httpContext); - } -} - -public static class FortunesEfMiddlewareExtensions -{ - public static IApplicationBuilder UseFortunesEf(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesRawMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesRawMiddleware.cs deleted file mode 100644 index d05baa3a93b..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/FortunesRawMiddleware.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -using System.Text.Encodings.Web; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class FortunesRawMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbFortunesRaw)); - - private readonly RequestDelegate _next; - private readonly HtmlEncoder _htmlEncoder; - - public FortunesRawMiddleware(RequestDelegate next, HtmlEncoder htmlEncoder) - { - _next = next; - _htmlEncoder = htmlEncoder; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadFortunesRows(); - - await MiddlewareHelpers.RenderFortunesHtml(rows, httpContext, _htmlEncoder); - - return; - } - - await _next(httpContext); - } -} - -public static class FortunesRawMiddlewareExtensions -{ - public static IApplicationBuilder UseFortunesRaw(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/JsonMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/JsonMiddleware.cs deleted file mode 100644 index 48dc2174b0c..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/JsonMiddleware.cs +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; - -namespace Benchmarks.Middleware; - -public class JsonMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.Json)); - private const int _bufferSize = 27; - - private readonly RequestDelegate _next; - - public JsonMiddleware(RequestDelegate next) - { - _next = next; - } - - public Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - httpContext.Response.StatusCode = 200; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = _bufferSize; - - return JsonSerializer.SerializeAsync(httpContext.Response.Body, new JsonMessage { message = "Hello, World!" }); - } - - return _next(httpContext); - } -} - -public static class JsonMiddlewareExtensions -{ - public static IApplicationBuilder UseJson(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} - -public struct JsonMessage -{ - public string message { get; set; } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MiddlewareHelpers.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MiddlewareHelpers.cs deleted file mode 100644 index a08bcf225c4..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MiddlewareHelpers.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -using System.Globalization; -using System.Text; -using System.Text.Encodings.Web; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public static class MiddlewareHelpers -{ - public static int GetMultipleQueriesQueryCount(HttpContext httpContext) - { - var queries = 1; - var queriesRaw = httpContext.Request.Query["queries"]; - - if (queriesRaw.Count == 1) - { - int.TryParse(queriesRaw, out queries); - } - - return queries > 500 - ? 500 - : queries > 0 - ? queries - : 1; - } - - public static Task RenderFortunesHtml(IEnumerable model, HttpContext httpContext, HtmlEncoder htmlEncoder) - { - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "text/html; charset=UTF-8"; - - var sb = StringBuilderCache.Acquire(); - sb.Append("Fortunesidmessage"); - foreach (var item in model) - { - sb.Append(""); - sb.Append(item.Id.ToString(CultureInfo.InvariantCulture)); - sb.Append(""); - sb.Append(htmlEncoder.Encode(item.Message)); - sb.Append(""); - } - - sb.Append(""); - var response = StringBuilderCache.GetStringAndRelease(sb); - // fortunes includes multibyte characters so response.Length is incorrect - httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(response); - return httpContext.Response.WriteAsync(response); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesDapperMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesDapperMiddleware.cs deleted file mode 100644 index 9bc35ace050..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesDapperMiddleware.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleQueriesDapperMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiQueryDapper)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public MultipleQueriesDapperMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleQueriesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleQueriesDapperMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleQueriesDapper(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesEfMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesEfMiddleware.cs deleted file mode 100644 index f8362cbbb4d..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesEfMiddleware.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleQueriesEfMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiQueryEf)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public MultipleQueriesEfMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleQueriesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleQueriesEfMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleQueriesEf(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesRawMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesRawMiddleware.cs deleted file mode 100644 index f4185f7f3be..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleQueriesRawMiddleware.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleQueriesRawMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiQueryRaw)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public MultipleQueriesRawMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleQueriesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleQueriesRawMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleQueriesRaw(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesDapperMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesDapperMiddleware.cs deleted file mode 100644 index 80478ed76d6..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesDapperMiddleware.cs +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleUpdatesDapperMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiUpdateDapper)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - private readonly RequestDelegate _next; - - public MultipleUpdatesDapperMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleUpdatesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleUpdatesDapperMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleUpdatesDapper(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesEfMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesEfMiddleware.cs deleted file mode 100644 index cb54020473b..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesEfMiddleware.cs +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleUpdatesEfMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiUpdateEf)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - private readonly RequestDelegate _next; - - public MultipleUpdatesEfMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleUpdatesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleUpdatesEfMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleUpdatesEf(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.cs deleted file mode 100644 index 116b67d1581..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.cs +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class MultipleUpdatesRawMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbMultiUpdateRaw)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public MultipleUpdatesRawMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var count = MiddlewareHelpers.GetMultipleQueriesQueryCount(httpContext); - - var db = httpContext.RequestServices.GetService(); - var rows = await db.LoadMultipleUpdatesRows(count); - - var result = JsonSerializer.Serialize(rows, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class MultipleUpdatesRawMiddlewareExtensions -{ - public static IApplicationBuilder UseMultipleUpdatesRaw(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/PlaintextMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/PlaintextMiddleware.cs deleted file mode 100644 index 99b9389dd6c..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/PlaintextMiddleware.cs +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -using System.Text; -using Benchmarks.Configuration; - -namespace Benchmarks.Middleware; - -public class PlaintextMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.Plaintext)); - private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); - - private readonly RequestDelegate _next; - - public PlaintextMiddleware(RequestDelegate next) - { - _next = next; - } - - public Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - return WriteResponse(httpContext.Response); - } - - return _next(httpContext); - } - - public static Task WriteResponse(HttpResponse response) - { - var payloadLength = _helloWorldPayload.Length; - response.StatusCode = 200; - response.ContentType = "text/plain"; - response.ContentLength = payloadLength; - return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); - } -} - -public static class PlaintextMiddlewareExtensions -{ - public static IApplicationBuilder UsePlainText(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryDapperMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryDapperMiddleware.cs deleted file mode 100644 index 580db19b957..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryDapperMiddleware.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class SingleQueryDapperMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbSingleQueryDapper)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public SingleQueryDapperMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var row = await db.LoadSingleQueryRow(); - - var result = JsonSerializer.Serialize(row, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class SingleQueryDapperMiddlewareExtensions -{ - public static IApplicationBuilder UseSingleQueryDapper(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryEfMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryEfMiddleware.cs deleted file mode 100644 index 68ac4e09aa2..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryEfMiddleware.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class SingleQueryEfMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbSingleQueryEf)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public SingleQueryEfMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var row = await db.LoadSingleQueryRow(); - var result = JsonSerializer.Serialize(row, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class SingleQueryEfMiddlewareExtensions -{ - public static IApplicationBuilder UseSingleQueryEf(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryRawMiddleware.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryRawMiddleware.cs deleted file mode 100644 index aa1e73bcb90..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Middleware/SingleQueryRawMiddleware.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -using System.Text.Json; -using Benchmarks.Configuration; -using Benchmarks.Data; - -namespace Benchmarks.Middleware; - -public class SingleQueryRawMiddleware -{ - private static readonly PathString _path = new(Scenarios.GetPath(s => s.DbSingleQueryRaw)); - private static readonly JsonSerializerOptions _serializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - - private readonly RequestDelegate _next; - - public SingleQueryRawMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.StartsWithSegments(_path, StringComparison.Ordinal)) - { - var db = httpContext.RequestServices.GetService(); - var row = await db.LoadSingleQueryRow(); - - var result = JsonSerializer.Serialize(row, _serializerOptions); - - httpContext.Response.StatusCode = StatusCodes.Status200OK; - httpContext.Response.ContentType = "application/json"; - httpContext.Response.ContentLength = result.Length; - - await httpContext.Response.WriteAsync(result); - - return; - } - - await _next(httpContext); - } -} - -public static class SingleQueryRawMiddlewareExtensions -{ - public static IApplicationBuilder UseSingleQueryRaw(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.Designer.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.Designer.cs deleted file mode 100644 index 4ea189b2563..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.Designer.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Benchmarks.Data; - -namespace Benchmarks.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20151113004227_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "7.0.0-rc2-16329") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("AspNet5.Data.World", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("RandomNumber"); - - b.HasKey("Id"); - }); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.cs deleted file mode 100644 index 63de764aa9e..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151113004227_Initial.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Metadata; -using System.Text; - -namespace Benchmarks.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "World", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - RandomNumber = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_World", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable("World"); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.Designer.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.Designer.cs deleted file mode 100644 index 0267669cb06..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.Designer.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Benchmarks.Data; - -namespace Benchmarks.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20151124205054_Fortune")] - partial class Fortune - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "7.0.0-rc2-16413") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Benchmarks.Data.Fortune", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Message") - .HasAnnotation("MaxLength", 2048); - - b.HasKey("Id"); - }); - - modelBuilder.Entity("Benchmarks.Data.World", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("RandomNumber"); - - b.HasKey("Id"); - }); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.cs deleted file mode 100644 index 9488d18d0f5..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/20151124205054_Fortune.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Metadata; - -namespace Benchmarks.Migrations -{ - public partial class Fortune : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Fortune", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Message = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Fortune", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Fortune"); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/ApplicationDbContextModelSnapshot.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/ApplicationDbContextModelSnapshot.cs deleted file mode 100644 index 320af52ff2d..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Migrations/ApplicationDbContextModelSnapshot.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Benchmarks.Data; - -namespace Benchmarks.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - partial class ApplicationDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "7.0.0-rc2-16413") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - modelBuilder.Entity("Benchmarks.Data.Fortune", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Message") - .HasAnnotation("MaxLength", 2048); - - b.HasKey("Id"); - }); - - modelBuilder.Entity("Benchmarks.Data.World", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("RandomNumber"); - - b.HasKey("Id"); - }); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/NuGet.Config b/frameworks/CSharp/aspnetcore/Benchmarks/NuGet.Config deleted file mode 100644 index f05d5867888..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/NuGet.Config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Program.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Program.cs deleted file mode 100644 index 45cf779a9a6..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Program.cs +++ /dev/null @@ -1,68 +0,0 @@ -// 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. - -using System.Reflection; -using System.Runtime; -using Benchmarks.Configuration; - -namespace Benchmarks; - -public class Program -{ - public static string[] Args; - - public static void Main(string[] args) - { - Args = args; - - Console.WriteLine(); - Console.WriteLine("ASP.NET Core Benchmarks"); - Console.WriteLine("-----------------------"); - - Console.WriteLine($"Current directory: {Directory.GetCurrentDirectory()}"); - Console.WriteLine($"WebHostBuilder loading from: {typeof(WebHostBuilder).GetTypeInfo().Assembly.Location}"); - - var config = new ConfigurationBuilder() - .AddJsonFile("hosting.json", optional: true) - .AddEnvironmentVariables(prefix: "ASPNETCORE_") - .AddCommandLine(args) - .Build(); - - var webHostBuilder = new WebHostBuilder() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseConfiguration(config) - .UseStartup() - .ConfigureServices(services => services - .AddSingleton(new ConsoleArgs(args)) - .AddSingleton() - .AddSingleton() - ) - .UseDefaultServiceProvider( - (context, options) => options.ValidateScopes = context.HostingEnvironment.IsDevelopment()) - .UseKestrel(); - - var threadCount = GetThreadCount(config); - - webHostBuilder.UseSockets(x => - { - if (threadCount > 0) - { - x.IOQueueCount = threadCount; - } - - Console.WriteLine($"Using Sockets with {x.IOQueueCount} threads"); - }); - - var webHost = webHostBuilder.Build(); - - Console.WriteLine($"Server GC is currently {(GCSettings.IsServerGC ? "ENABLED" : "DISABLED")}"); - - webHost.Run(); - } - - private static int GetThreadCount(IConfigurationRoot config) - { - var threadCountValue = config["threadCount"]; - return threadCountValue == null ? -1 : int.Parse(threadCountValue); - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Startup.cs b/frameworks/CSharp/aspnetcore/Benchmarks/Startup.cs deleted file mode 100644 index b9a90524c3a..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Startup.cs +++ /dev/null @@ -1,208 +0,0 @@ -// 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. - -using Benchmarks.Configuration; -using Benchmarks.Data; -using Benchmarks.Middleware; -using Microsoft.EntityFrameworkCore; -using MySqlConnector; -using Npgsql; -using System.Data.Common; -using System.Text.Encodings.Web; -using System.Text.Unicode; -using Microsoft.EntityFrameworkCore.Storage; - -namespace Benchmarks; - -public class Startup -{ - public Startup(IWebHostEnvironment hostingEnv, Scenarios scenarios) - { - // Set up configuration sources. - var builder = new ConfigurationBuilder() - .SetBasePath(hostingEnv.ContentRootPath) - .AddJsonFile("appsettings.json") - .AddJsonFile($"appsettings.{hostingEnv.EnvironmentName}.json", optional: true) - .AddEnvironmentVariables() - .AddCommandLine(Program.Args) - ; - - Configuration = builder.Build(); - - Scenarios = scenarios; - } - - public IConfigurationRoot Configuration { get; set; } - - public Scenarios Scenarios { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.Configure(Configuration); - - // We re-register the Scenarios as an instance singleton here to avoid it being created again due to the - // registration done in Program.Main - services.AddSingleton(Scenarios); - - // Common DB services - services.AddSingleton(); - services.AddEntityFrameworkSqlServer(); - - var appSettings = Configuration.Get(); - BatchUpdateString.DatabaseServer = appSettings.Database; - - Console.WriteLine($"Database: {appSettings.Database}"); - - if (appSettings.Database == DatabaseServer.PostgreSql) - { - if (Scenarios.Any("Ef")) - { - services.AddDbContextPool(options => options - .UseNpgsql(appSettings.ConnectionString, - o => o.ExecutionStrategy(d => new NonRetryingExecutionStrategy(d))) - .EnableThreadSafetyChecks(false)); - } - - if (Scenarios.Any("Raw") || Scenarios.Any("Dapper")) - { - services.AddSingleton(NpgsqlFactory.Instance); - } - } - else if (appSettings.Database == DatabaseServer.MySql) - { - if (Scenarios.Any("Raw") || Scenarios.Any("Dapper")) - { - services.AddSingleton(MySqlConnectorFactory.Instance); - } - } - - if (Scenarios.Any("Ef")) - { - services.AddScoped(); - } - - if (Scenarios.Any("Raw")) - { - services.AddScoped(); - } - - if (Scenarios.Any("Dapper")) - { - services.AddScoped(); - } - - if (Scenarios.Any("Fortunes")) - { - var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana); - settings.AllowCharacter('\u2014'); // allow EM DASH through - services.AddWebEncoders((options) => - { - options.TextEncoderSettings = settings; - }); - } - - if (Scenarios.Any("Mvc")) - { - var mvcBuilder = services.AddMvcCore(); - - if (Scenarios.MvcViews || Scenarios.Any("MvcDbFortunes")) - { - mvcBuilder - .AddViews() - .AddRazorViewEngine(); - } - } - } - - public void Configure(IApplicationBuilder app) - { - if (Scenarios.Plaintext) - { - app.UsePlainText(); - } - - if (Scenarios.Json) - { - app.UseJson(); - } - - // Fortunes endpoints - if (Scenarios.DbFortunesRaw) - { - app.UseFortunesRaw(); - } - - if (Scenarios.DbFortunesDapper) - { - app.UseFortunesDapper(); - } - - if (Scenarios.DbFortunesEf) - { - app.UseFortunesEf(); - } - - // Single query endpoints - if (Scenarios.DbSingleQueryRaw) - { - app.UseSingleQueryRaw(); - } - - if (Scenarios.DbSingleQueryDapper) - { - app.UseSingleQueryDapper(); - } - - if (Scenarios.DbSingleQueryEf) - { - app.UseSingleQueryEf(); - } - - // Multiple query endpoints - if (Scenarios.DbMultiQueryRaw) - { - app.UseMultipleQueriesRaw(); - } - - if (Scenarios.DbMultiQueryDapper) - { - app.UseMultipleQueriesDapper(); - } - - if (Scenarios.DbMultiQueryEf) - { - app.UseMultipleQueriesEf(); - } - - // Multiple update endpoints - if (Scenarios.DbMultiUpdateRaw) - { - app.UseMultipleUpdatesRaw(); - } - - if (Scenarios.DbMultiUpdateDapper) - { - app.UseMultipleUpdatesDapper(); - } - - if (Scenarios.DbMultiUpdateEf) - { - app.UseMultipleUpdatesEf(); - } - - if (Scenarios.Any("Mvc")) - { - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - - if (Scenarios.StaticFiles) - { - app.UseStaticFiles(); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Views/Fortunes/Fortunes.cshtml b/frameworks/CSharp/aspnetcore/Benchmarks/Views/Fortunes/Fortunes.cshtml deleted file mode 100644 index 17d7ef14a24..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Views/Fortunes/Fortunes.cshtml +++ /dev/null @@ -1,12 +0,0 @@ -@using Benchmarks.Data -@model List - - -Fortunes -idmessage - @foreach (var item in Model) - { - @item.Id@item.Message - } - - diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/Views/Home/Index.cshtml b/frameworks/CSharp/aspnetcore/Benchmarks/Views/Home/Index.cshtml deleted file mode 100644 index 3e8acf9440a..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/Views/Home/Index.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@{ - var message = "Hello, World!"; -} - -@message \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/appsettings.json b/frameworks/CSharp/aspnetcore/Benchmarks/appsettings.json deleted file mode 100644 index d7a356382f6..00000000000 --- a/frameworks/CSharp/aspnetcore/Benchmarks/appsettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnetcore-Benchmarks;Trusted_Connection=True;MultipleActiveResultSets=true" -} diff --git a/frameworks/CSharp/aspnetcore/Benchmarks/wwwroot/1KB.txt b/frameworks/CSharp/aspnetcore/Benchmarks/wwwroot/1KB.txt deleted file mode 100644 index 06d74050200..00000000000 Binary files a/frameworks/CSharp/aspnetcore/Benchmarks/wwwroot/1KB.txt and /dev/null differ diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Caching.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Caching.cs deleted file mode 100644 index 2b8f1eb9243..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Caching.cs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 DATABASE - -using System.IO.Pipelines; -using System.Threading.Tasks; - -namespace PlatformBenchmarks; - -public partial class BenchmarkApplication -{ - private static async Task Caching(PipeWriter pipeWriter, int count) - { - OutputMultipleQueries(pipeWriter, await Db.LoadCachedQueries(count), SerializerContext.CachedWorldArray); - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Fortunes.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Fortunes.cs deleted file mode 100644 index 793d20af48b..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Fortunes.cs +++ /dev/null @@ -1,67 +0,0 @@ -// 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 DATABASE - -using System.IO.Pipelines; -using System.Runtime.CompilerServices; -using RazorSlices; - -namespace PlatformBenchmarks -{ - public partial class BenchmarkApplication - { - private async Task Fortunes(PipeWriter pipeWriter) - { - await OutputFortunes(pipeWriter, await Db.LoadFortunesRows(), FortunesTemplateFactory); - } - - private ValueTask OutputFortunes(PipeWriter pipeWriter, TModel model, SliceFactory templateFactory) - { - // Render headers - var preamble = """ - HTTP/1.1 200 OK - Server: K - Content-Type: text/html; charset=utf-8 - Transfer-Encoding: chunked - """u8; - var headersLength = preamble.Length + DateHeader.HeaderBytes.Length; - var headersSpan = pipeWriter.GetSpan(headersLength); - preamble.CopyTo(headersSpan); - DateHeader.HeaderBytes.CopyTo(headersSpan[preamble.Length..]); - pipeWriter.Advance(headersLength); - - // Render body - var template = templateFactory(model); - // 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); - - if (renderTask.IsCompletedSuccessfully) - { - renderTask.GetAwaiter().GetResult(); - EndTemplateRendering(chunkedWriter, template); - return ValueTask.CompletedTask; - } - - return AwaitTemplateRenderTask(renderTask, chunkedWriter, template); - } - - private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedBufferWriter chunkedWriter, RazorSlice template) - { - await renderTask; - EndTemplateRendering(chunkedWriter, template); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void EndTemplateRendering(ChunkedBufferWriter chunkedWriter, RazorSlice template) - { - chunkedWriter.End(); - ReturnChunkedWriter(chunkedWriter); - template.Dispose(); - } - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs deleted file mode 100644 index 1c31523cdfb..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs +++ /dev/null @@ -1,306 +0,0 @@ -// 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. - -using System.Buffers; -using System.IO.Pipelines; -using System.Runtime.CompilerServices; -using System.Text.Encodings.Web; -using System.Text.Unicode; -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; - -namespace PlatformBenchmarks; - -public partial class BenchmarkApplication : IHttpConnection -{ - private State _state; - - public PipeReader Reader { get; set; } - public PipeWriter Writer { get; set; } - - protected HtmlEncoder HtmlEncoder { get; } = CreateHtmlEncoder(); - - private HttpParser Parser { get; } = new HttpParser(); - - public async Task ExecuteAsync() - { - try - { - await ProcessRequestsAsync(); - - Reader.Complete(); - } - catch (Exception ex) - { - Reader.Complete(ex); - } - finally - { - Writer.Complete(); - } - } - - private static HtmlEncoder CreateHtmlEncoder() - { - var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana); - settings.AllowCharacter('\u2014'); // allow EM DASH through - return HtmlEncoder.Create(settings); - } - -#if !DATABASE - private async Task ProcessRequestsAsync() - { - while (true) - { - var readResult = await Reader.ReadAsync(default); - var buffer = readResult.Buffer; - var isCompleted = readResult.IsCompleted; - - if (buffer.IsEmpty && isCompleted) - { - return; - } - - if (!HandleRequests(buffer, isCompleted)) - { - return; - } - - await Writer.FlushAsync(default); - } - } - - private bool HandleRequests(in ReadOnlySequence buffer, bool isCompleted) - { - var reader = new SequenceReader(buffer); - var writer = GetWriter(Writer, sizeHint: 160 * 16); // 160*16 is for Plaintext, for Json 160 would be enough - - while (true) - { - if (!ParseHttpRequest(ref reader, isCompleted)) - { - return false; - } - - if (_state == State.Body) - { - ProcessRequest(ref writer); - - _state = State.StartLine; - - if (!reader.End) - { - // More input data to parse - continue; - } - } - - // No more input or incomplete data, Advance the Reader - Reader.AdvanceTo(reader.Position, buffer.End); - break; - } - - writer.Commit(); - return true; - } - - private bool ParseHttpRequest(ref SequenceReader reader, bool isCompleted) - { - var state = _state; - - if (state == State.StartLine) - { - if (Parser.ParseRequestLine(new ParsingAdapter(this), ref reader)) - { - state = State.Headers; - } - } - - if (state == State.Headers) - { - var success = Parser.ParseHeaders(new ParsingAdapter(this), ref reader); - - if (success) - { - state = State.Body; - } - } - - if (state != State.Body && isCompleted) - { - ThrowUnexpectedEndOfData(); - } - - _state = state; - return true; - } -#else - private async Task ProcessRequestsAsync() - { - while (true) - { - var readResult = await Reader.ReadAsync(); - var buffer = readResult.Buffer; - var isCompleted = readResult.IsCompleted; - - if (buffer.IsEmpty && isCompleted) - { - return; - } - - while (true) - { - if (!ParseHttpRequest(ref buffer, isCompleted)) - { - return; - } - - if (_state == State.Body) - { - await ProcessRequestAsync(); - - _state = State.StartLine; - - if (!buffer.IsEmpty) - { - // More input data to parse - continue; - } - } - - // No more input or incomplete data, Advance the Reader - Reader.AdvanceTo(buffer.Start, buffer.End); - break; - } - - await Writer.FlushAsync(); - } - } - - private bool ParseHttpRequest(ref ReadOnlySequence buffer, bool isCompleted) - { - var reader = new SequenceReader(buffer); - var state = _state; - - if (state == State.StartLine) - { - if (Parser.ParseRequestLine(new ParsingAdapter(this), ref reader)) - { - state = State.Headers; - } - } - - if (state == State.Headers) - { - var success = Parser.ParseHeaders(new ParsingAdapter(this), ref reader); - - if (success) - { - state = State.Body; - } - } - - if (state != State.Body && isCompleted) - { - ThrowUnexpectedEndOfData(); - } - - _state = state; - - if (state == State.Body) - { - // Complete request read, consumed and examined are the same (length 0) - buffer = buffer.Slice(reader.Position, 0); - } - else - { - // In-complete request read, consumed is current position and examined is the remaining. - buffer = buffer.Slice(reader.Position); - } - - return true; - } -#endif - - public void OnStaticIndexedHeader(int index) - { - } - - public void OnStaticIndexedHeader(int index, ReadOnlySpan value) - { - } - - public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) - { - } - - public void OnHeadersComplete(bool endStream) - { - } - - private static void ThrowUnexpectedEndOfData() - { - throw new InvalidOperationException("Unexpected end of data!"); - } - - private enum State - { - StartLine, - Headers, - Body - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static BufferWriter GetWriter(PipeWriter pipeWriter, int sizeHint) - => new(new(pipeWriter), sizeHint); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ChunkedBufferWriter GetChunkedWriter(PipeWriter pipeWriter, int chunkSizeHint) - { - var writer = ChunkedWriterPool.Get(); - writer.SetOutput(new WriterAdapter(pipeWriter), chunkSizeHint); - return writer; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void ReturnChunkedWriter(ChunkedBufferWriter writer) => ChunkedWriterPool.Return(writer); - - private struct WriterAdapter : IBufferWriter - { - public PipeWriter Writer; - - public WriterAdapter(PipeWriter writer) - => Writer = writer; - - public void Advance(int count) - => Writer.Advance(count); - - public Memory GetMemory(int sizeHint = 0) - => Writer.GetMemory(sizeHint); - - public Span GetSpan(int sizeHint = 0) - => Writer.GetSpan(sizeHint); - } - - private struct ParsingAdapter : IHttpRequestLineHandler, IHttpHeadersHandler - { - public BenchmarkApplication RequestHandler; - - public ParsingAdapter(BenchmarkApplication requestHandler) - => RequestHandler = requestHandler; - - public void OnStaticIndexedHeader(int index) - => RequestHandler.OnStaticIndexedHeader(index); - - public void OnStaticIndexedHeader(int index, ReadOnlySpan value) - => RequestHandler.OnStaticIndexedHeader(index, value); - - public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) - => RequestHandler.OnHeader(name, value); - - public void OnHeadersComplete(bool endStream) - => RequestHandler.OnHeadersComplete(endStream); - - public void OnStartLine(HttpVersionAndMethod versionAndMethod, TargetOffsetPathLength targetPath, Span startLine) - => RequestHandler.OnStartLine(versionAndMethod, targetPath, startLine); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Json.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Json.cs deleted file mode 100644 index 186eefc8105..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Json.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -using System.Buffers; -using System.Text.Json; - -namespace PlatformBenchmarks; - -public partial class BenchmarkApplication -{ - private readonly static uint _jsonPayloadSize = (uint)JsonSerializer.SerializeToUtf8Bytes(new JsonMessage { message = "Hello, World!" }, SerializerContext.JsonMessage).Length; - - private static ReadOnlySpan _jsonPreamble => - "HTTP/1.1 200 OK\r\n"u8 + - "Server: K\r\n"u8 + - "Content-Type: application/json\r\n"u8 + - "Content-Length: 27"u8; - - private static void Json(ref BufferWriter writer, IBufferWriter bodyWriter) - { - writer.Write(_jsonPreamble); - - // Date header - writer.Write(DateHeader.HeaderBytes); - - writer.Commit(); - - var utf8JsonWriter = t_writer ??= new Utf8JsonWriter(bodyWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(bodyWriter); - - // Body - JsonSerializer.Serialize(utf8JsonWriter, new JsonMessage { message = "Hello, World!" }, SerializerContext.JsonMessage); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.MultipleQueries.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.MultipleQueries.cs deleted file mode 100644 index eab6278eb4b..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.MultipleQueries.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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 DATABASE - -using System.IO.Pipelines; -using System.Text.Json; -using System.Text.Json.Serialization.Metadata; -using System.Threading.Tasks; - -namespace PlatformBenchmarks -{ - public partial class BenchmarkApplication - { - private static async Task MultipleQueries(PipeWriter pipeWriter, int count) - { - OutputMultipleQueries(pipeWriter, await Db.LoadMultipleQueriesRows(count), SerializerContext.WorldArray); - } - - private static void OutputMultipleQueries(PipeWriter pipeWriter, TWorld[] rows, JsonTypeInfo jsonTypeInfo) - { - var writer = GetWriter(pipeWriter, sizeHint: 160 * rows.Length); // in reality it's 152 for one - - writer.Write(_dbPreamble); - - var lengthWriter = writer; - writer.Write(_contentLengthGap); - - // Date header - writer.Write(DateHeader.HeaderBytes); - - writer.Commit(); - - var utf8JsonWriter = t_writer ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(pipeWriter); - - // Body - JsonSerializer.Serialize(utf8JsonWriter, rows, jsonTypeInfo); - - // Content-Length - lengthWriter.WriteNumeric((uint)utf8JsonWriter.BytesCommitted); - } - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Plaintext.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Plaintext.cs deleted file mode 100644 index 16a7c0f76eb..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Plaintext.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public partial class BenchmarkApplication -{ - private static ReadOnlySpan _plaintextPreamble => - "HTTP/1.1 200 OK\r\n"u8 + - "Server: K\r\n"u8 + - "Content-Type: text/plain\r\n"u8 + - "Content-Length: 13"u8; - - private static void PlainText(ref BufferWriter writer) - { - writer.Write(_plaintextPreamble); - - // Date header - writer.Write(DateHeader.HeaderBytes); - - // Body - writer.Write(_plainTextBody); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.SingleQuery.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.SingleQuery.cs deleted file mode 100644 index 31c12060179..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.SingleQuery.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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 DATABASE - -using System.IO.Pipelines; -using System.Text.Json; -using System.Threading.Tasks; - -namespace PlatformBenchmarks -{ - public partial class BenchmarkApplication - { - private static async Task SingleQuery(PipeWriter pipeWriter) - { - OutputSingleQuery(pipeWriter, await Db.LoadSingleQueryRow()); - } - - private static void OutputSingleQuery(PipeWriter pipeWriter, World row) - { - var writer = GetWriter(pipeWriter, sizeHint: 180); // in reality it's 150 - - writer.Write(_dbPreamble); - - var lengthWriter = writer; - writer.Write(_contentLengthGap); - - // Date header - writer.Write(DateHeader.HeaderBytes); - - writer.Commit(); - - var utf8JsonWriter = t_writer ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(pipeWriter); - - // Body - JsonSerializer.Serialize(utf8JsonWriter, row, SerializerContext.World); - - // Content-Length - lengthWriter.WriteNumeric((uint)utf8JsonWriter.BytesCommitted); - } - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Updates.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Updates.cs deleted file mode 100644 index 91a164ae6a2..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.Updates.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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 DATABASE - -using System.IO.Pipelines; -using System.Text.Json; -using System.Threading.Tasks; - -namespace PlatformBenchmarks -{ - public partial class BenchmarkApplication - { - private static async Task Updates(PipeWriter pipeWriter, int count) - { - OutputUpdates(pipeWriter, await Db.LoadMultipleUpdatesRows(count)); - } - - private static void OutputUpdates(PipeWriter pipeWriter, World[] rows) - { - var writer = GetWriter(pipeWriter, sizeHint: 120 * rows.Length); // in reality it's 112 for one - - writer.Write(_dbPreamble); - - var lengthWriter = writer; - writer.Write(_contentLengthGap); - - // Date header - writer.Write(DateHeader.HeaderBytes); - - writer.Commit(); - - var utf8JsonWriter = t_writer ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(pipeWriter); - - // Body - JsonSerializer.Serialize(utf8JsonWriter, rows, SerializerContext.WorldArray); - - // Content-Length - lengthWriter.WriteNumeric((uint)utf8JsonWriter.BytesCommitted); - } - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.cs deleted file mode 100644 index a25b2a4abe7..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkApplication.cs +++ /dev/null @@ -1,210 +0,0 @@ -// 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. - -using System; -using System.Buffers.Text; -using System.IO.Pipelines; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; -using Microsoft.Extensions.ObjectPool; -using RazorSlices; - -namespace PlatformBenchmarks; - -public sealed partial class BenchmarkApplication -{ - public static ReadOnlySpan ApplicationName => "Kestrel Platform-Level Application"u8; - - private static ReadOnlySpan _crlf => "\r\n"u8; - private static ReadOnlySpan _eoh => "\r\n\r\n"u8; // End Of Headers - private static ReadOnlySpan _http11OK => "HTTP/1.1 200 OK\r\n"u8; - private static ReadOnlySpan _http11NotFound => "HTTP/1.1 404 Not Found\r\n"u8; - private static ReadOnlySpan _headerServer => "Server: K"u8; - private static ReadOnlySpan _headerContentLength => "Content-Length: "u8; - private static ReadOnlySpan _headerContentLengthZero => "Content-Length: 0"u8; - private static ReadOnlySpan _headerContentTypeText => "Content-Type: text/plain"u8; - private static ReadOnlySpan _headerContentTypeJson => "Content-Type: application/json"u8; - private static ReadOnlySpan _headerContentTypeHtml => "Content-Type: text/html; charset=UTF-8"u8; - - private static ReadOnlySpan _dbPreamble => - "HTTP/1.1 200 OK\r\n"u8 + - "Server: K\r\n"u8 + - "Content-Type: application/json\r\n"u8 + - "Content-Length: "u8; - - private static ReadOnlySpan _plainTextBody => "Hello, World!"u8; - private static ReadOnlySpan _contentLengthGap => " "u8; - -#if DATABASE - public static RawDb Db { get; set; } -#endif - - private static readonly DefaultObjectPool> ChunkedWriterPool - = new(new ChunkedWriterObjectPolicy()); - - private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy> - { - public ChunkedBufferWriter Create() => new(); - - public bool Return(ChunkedBufferWriter writer) - { - writer.Reset(); - return true; - } - } - -#if DATABASE - private readonly static SliceFactory> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory>("/Templates/FortunesUtf8.cshtml"); -#endif - - [ThreadStatic] - private static Utf8JsonWriter t_writer; - - private static readonly JsonContext SerializerContext = JsonContext.Default; - - [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] - [JsonSerializable(typeof(JsonMessage))] - [JsonSerializable(typeof(CachedWorld[]))] - [JsonSerializable(typeof(World[]))] - private sealed partial class JsonContext : JsonSerializerContext - { - } - - public static class Paths - { - public static ReadOnlySpan Json => "/json"u8; - public static ReadOnlySpan Plaintext => "/plaintext"u8; - public static ReadOnlySpan SingleQuery => "/db"u8; - public static ReadOnlySpan Fortunes => "/fortunes"u8; - public static ReadOnlySpan Updates => "/updates/"u8; - public static ReadOnlySpan MultipleQueries => "/queries/"u8; - public static ReadOnlySpan Caching => "/cached-worlds/"u8; - } - - private RequestType _requestType; - private int _queries; - - public void OnStartLine(HttpVersionAndMethod versionAndMethod, TargetOffsetPathLength targetPath, Span startLine) - { - _requestType = versionAndMethod.Method == Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpMethod.Get ? GetRequestType(startLine.Slice(targetPath.Offset, targetPath.Length), ref _queries) : RequestType.NotRecognized; - } - - private static RequestType GetRequestType(ReadOnlySpan path, ref int queries) - { -#if !DATABASE - if (path.Length == 10 && path.SequenceEqual(Paths.Plaintext)) - { - return RequestType.PlainText; - } - if (path.Length == 5 && path.SequenceEqual(Paths.Json)) - { - return RequestType.Json; - } -#else - if (path.Length == 3 && path[0] == '/' && path[1] == 'd' && path[2] == 'b') - { - return RequestType.SingleQuery; - } - if (path.Length == 9 && path[1] == 'f' && path.SequenceEqual(Paths.Fortunes)) - { - return RequestType.Fortunes; - } - if (path.Length >= 15 && path[1] == 'c' && path.StartsWith(Paths.Caching)) - { - queries = ParseQueries(path.Slice(15)); - return RequestType.Caching; - } - if (path.Length >= 9 && path[1] == 'u' && path.StartsWith(Paths.Updates)) - { - queries = ParseQueries(path.Slice(9)); - return RequestType.Updates; - } - if (path.Length >= 9 && path[1] == 'q' && path.StartsWith(Paths.MultipleQueries)) - { - queries = ParseQueries(path.Slice(9)); - return RequestType.MultipleQueries; - } -#endif - return RequestType.NotRecognized; - } - - -#if !DATABASE - private void ProcessRequest(ref BufferWriter writer) - { - if (_requestType == RequestType.PlainText) - { - PlainText(ref writer); - } - else if (_requestType == RequestType.Json) - { - Json(ref writer, Writer); - } - else - { - Default(ref writer); - } - } -#else - - private static int ParseQueries(ReadOnlySpan parameter) - { - if (!Utf8Parser.TryParse(parameter, out int queries, out _)) - { - queries = 1; - } - else - { - queries = Math.Clamp(queries, 1, 500); - } - - return queries; - } - - private Task ProcessRequestAsync() => _requestType switch - { - RequestType.Fortunes => Fortunes(Writer), - RequestType.SingleQuery => SingleQuery(Writer), - RequestType.Caching => Caching(Writer, _queries), - RequestType.Updates => Updates(Writer, _queries), - RequestType.MultipleQueries => MultipleQueries(Writer, _queries), - _ => Default(Writer) - }; - - private static Task Default(PipeWriter pipeWriter) - { - var writer = GetWriter(pipeWriter, sizeHint: _defaultPreamble.Length + DateHeader.HeaderBytes.Length); - Default(ref writer); - writer.Commit(); - return Task.CompletedTask; - } -#endif - private static ReadOnlySpan _defaultPreamble => - "HTTP/1.1 200 OK\r\n"u8 + - "Server: K"u8 + "\r\n"u8 + - "Content-Type: text/plain"u8 + - "Content-Length: 0"u8; - - private static void Default(ref BufferWriter writer) - { - writer.Write(_defaultPreamble); - - // Date header - writer.Write(DateHeader.HeaderBytes); - } - - private enum RequestType - { - NotRecognized, - PlainText, - Json, - Fortunes, - SingleQuery, - Caching, - Updates, - MultipleQueries - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkConfigurationHelpers.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkConfigurationHelpers.cs deleted file mode 100644 index 87317b4fd97..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BenchmarkConfigurationHelpers.cs +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -using System.Net; -using System.Runtime.InteropServices; - -namespace PlatformBenchmarks; - -public static class BenchmarkConfigurationHelpers -{ - public static IWebHostBuilder UseBenchmarksConfiguration(this IWebHostBuilder builder, IConfiguration configuration) - { - builder.UseConfiguration(configuration); - - builder.UseSockets(options => - { - if (int.TryParse(builder.GetSetting("threadCount"), out var threadCount)) - { - options.IOQueueCount = threadCount; - } - - options.WaitForDataBeforeAllocatingBuffer = false; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - options.UnsafePreferInlineScheduling = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS") == "1"; - } - - Console.WriteLine($"Options: WaitForData={options.WaitForDataBeforeAllocatingBuffer}, PreferInlineScheduling={options.UnsafePreferInlineScheduling}, IOQueue={options.IOQueueCount}"); - }); - - return builder; - } - - public static IPEndPoint CreateIPEndPoint(this IConfiguration config) - { - var url = config["server.urls"] ?? config["urls"]; - - if (string.IsNullOrEmpty(url)) - { - return new IPEndPoint(IPAddress.Loopback, 8080); - } - - var address = BindingAddress.Parse(url); - - IPAddress ip; - - if (string.Equals(address.Host, "localhost", StringComparison.OrdinalIgnoreCase)) - { - ip = IPAddress.Loopback; - } - else if (!IPAddress.TryParse(address.Host, out ip)) - { - ip = IPAddress.IPv6Any; - } - - return new IPEndPoint(ip, address.Port); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferExtensions.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferExtensions.cs deleted file mode 100644 index 2fe34f0d0fa..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -using System; -using System.Buffers; -using System.Runtime.CompilerServices; -using System.Text; - -namespace PlatformBenchmarks; - -// Same as KestrelHttpServer\src\Kestrel.Core\Internal\Http\PipelineExtensions.cs -// However methods accept T : struct, IBufferWriter rather than PipeWriter. -// This allows a struct wrapper to turn CountingBufferWriter into a non-shared generic, -// while still offering the WriteNumeric extension. - -public static class BufferExtensions -{ - private const int _maxULongByteLength = 20; - - [ThreadStatic] - private static byte[] _numericBytesScratch; - - internal static void WriteUtf8String(ref this BufferWriter buffer, string text) - where T : struct, IBufferWriter - { - var byteCount = Encoding.UTF8.GetByteCount(text); - buffer.Ensure(byteCount); - byteCount = Encoding.UTF8.GetBytes(text.AsSpan(), buffer.Span); - buffer.Advance(byteCount); - } - [MethodImpl(MethodImplOptions.NoInlining)] - internal static void WriteNumericMultiWrite(ref this BufferWriter buffer, uint number) - where T : IBufferWriter - { - const byte AsciiDigitStart = (byte)'0'; - - var value = number; - var position = _maxULongByteLength; - var byteBuffer = NumericBytesScratch; - do - { - // Consider using Math.DivRem() if available - var quotient = value / 10; - byteBuffer[--position] = (byte)(AsciiDigitStart + (value - quotient * 10)); // 0x30 = '0' - value = quotient; - } - while (value != 0); - - var length = _maxULongByteLength - position; - buffer.Write(new ReadOnlySpan(byteBuffer, position, length)); - } - - private static byte[] NumericBytesScratch => _numericBytesScratch ?? CreateNumericBytesScratch(); - - [MethodImpl(MethodImplOptions.NoInlining)] - private static byte[] CreateNumericBytesScratch() - { - var bytes = new byte[_maxULongByteLength]; - _numericBytesScratch = bytes; - return bytes; - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferWriter.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferWriter.cs deleted file mode 100644 index e46b3303b77..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/BufferWriter.cs +++ /dev/null @@ -1,141 +0,0 @@ -// 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. - -using System.Buffers; -using System.Runtime.CompilerServices; - -namespace PlatformBenchmarks; - -public ref struct BufferWriter where T : IBufferWriter -{ - private readonly T _output; - private Span _span; - private int _buffered; - - public BufferWriter(T output, int sizeHint) - { - _buffered = 0; - _output = output; - _span = output.GetSpan(sizeHint); - } - - public Span Span => _span; - - public T Output => _output; - - public int Buffered => _buffered; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Commit() - { - var buffered = _buffered; - if (buffered > 0) - { - _buffered = 0; - _output.Advance(buffered); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Advance(int count) - { - _buffered += count; - _span = _span.Slice(count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(scoped ReadOnlySpan source) - { - if (_span.Length >= source.Length) - { - source.CopyTo(_span); - Advance(source.Length); - } - else - { - WriteMultiBuffer(source); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Ensure(int count = 1) - { - if (_span.Length < count) - { - EnsureMore(count); - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private void EnsureMore(int count = 0) - { - if (_buffered > 0) - { - Commit(); - } - - _span = _output.GetSpan(count); - } - - private void WriteMultiBuffer(scoped ReadOnlySpan source) - { - while (source.Length > 0) - { - if (_span.Length == 0) - { - EnsureMore(); - } - - var writable = Math.Min(source.Length, _span.Length); - source[..writable].CopyTo(_span); - source = source[writable..]; - Advance(writable); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void WriteNumeric(uint number) - { - const byte AsciiDigitStart = (byte)'0'; - - var span = this.Span; - - // Fast path, try copying to the available memory directly - var advanceBy = 0; - if (span.Length >= 3) - { - if (number < 10) - { - span[0] = (byte)(number + AsciiDigitStart); - advanceBy = 1; - } - else if (number < 100) - { - var tens = (byte)((number * 205u) >> 11); // div10, valid to 1028 - - span[0] = (byte)(tens + AsciiDigitStart); - span[1] = (byte)(number - (tens * 10) + AsciiDigitStart); - advanceBy = 2; - } - else if (number < 1000) - { - var digit0 = (byte)((number * 41u) >> 12); // div100, valid to 1098 - var digits01 = (byte)((number * 205u) >> 11); // div10, valid to 1028 - - span[0] = (byte)(digit0 + AsciiDigitStart); - span[1] = (byte)(digits01 - (digit0 * 10) + AsciiDigitStart); - span[2] = (byte)(number - (digits01 * 10) + AsciiDigitStart); - advanceBy = 3; - } - } - - if (advanceBy > 0) - { - Advance(advanceBy); - } - else - { - BufferExtensions.WriteNumericMultiWrite(ref this, number); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/ChunkedBufferWriter.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/ChunkedBufferWriter.cs deleted file mode 100644 index b63f0775332..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/ChunkedBufferWriter.cs +++ /dev/null @@ -1,241 +0,0 @@ -// 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. - -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Diagnostics; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace PlatformBenchmarks; - -internal sealed class ChunkedBufferWriter : IBufferWriter where TWriter : IBufferWriter -{ - private const int DefaultChunkSizeHint = 2048; - private static readonly StandardFormat DefaultHexFormat = GetHexFormat(DefaultChunkSizeHint); - private static ReadOnlySpan ChunkTerminator => "\r\n"u8; - - private TWriter _output; - private int _chunkSizeHint; - private StandardFormat _hexFormat = DefaultHexFormat; - private Memory _currentFullChunk; - private Memory _currentChunk; - private int _buffered; - private bool _ended = false; - - public Memory Memory => _currentChunk; - - public TWriter Output => _output; - - public int Buffered => _buffered; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetOutput(TWriter output, int chunkSizeHint = DefaultChunkSizeHint) - { - _buffered = 0; - _chunkSizeHint = chunkSizeHint; - _output = output; - - StartNewChunk(chunkSizeHint, isFirst: true); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Reset() - { - _buffered = 0; - _output = default; - _ended = false; - _hexFormat = DefaultHexFormat; - _currentFullChunk = default; - _currentChunk = default; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Advance(int count) - { - ThrowIfEnded(); - - _buffered += count; - _currentChunk = _currentChunk[count..]; - } - - public Memory GetMemory(int sizeHint = 0) - { - ThrowIfEnded(); - - if (_currentChunk.Length <= sizeHint) - { - EnsureMore(sizeHint); - } - return _currentChunk; - } - - public Span GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span; - - public void End() - { - ThrowIfEnded(); - - CommitCurrentChunk(isFinal: true); - - _ended = true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static StandardFormat GetHexFormat(int maxValue) - { - var hexDigitCount = CountHexDigits(maxValue); - - return new StandardFormat('X', (byte)hexDigitCount); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int CountHexDigits(int n) => n <= 16 ? 1 : (BitOperations.Log2((uint)n) >> 2) + 1; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void StartNewChunk(int sizeHint, bool isFirst = false) - { - ThrowIfEnded(); - - // Header is like: - // 520\r\n - - var oldFullChunkHexLength = -1; - if (!isFirst) - { - oldFullChunkHexLength = CountHexDigits(_currentFullChunk.Length); - } - _currentFullChunk = _output.GetMemory(Math.Max(_chunkSizeHint, sizeHint)); - var newFullChunkHexLength = CountHexDigits(_currentFullChunk.Length); - - var currentFullChunkSpan = _currentFullChunk.Span; - - // Write space for HEX digits - currentFullChunkSpan[..newFullChunkHexLength].Fill(48); // 48 == '0' - - // Write header terminator - var terminator = "\r\n"u8; - terminator.CopyTo(currentFullChunkSpan[newFullChunkHexLength..]); - var chunkHeaderLength = newFullChunkHexLength + terminator.Length; - _currentChunk = _currentFullChunk[chunkHeaderLength..]; - - if ((!isFirst && oldFullChunkHexLength != newFullChunkHexLength) || (isFirst && DefaultChunkSizeHint != _chunkSizeHint)) - { - // Update HEX format if changed - _hexFormat = GetHexFormat(_currentFullChunk.Length); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CommitCurrentChunk(bool isFinal = false, int sizeHint = 0) - { - ThrowIfEnded(); - - var contentLength = _buffered; - - if (contentLength > 0) - { - // Update the chunk header - var chunkLengthHexDigitsLength = CountHexDigits(contentLength); - var span = _currentFullChunk.Span; - if (!Utf8Formatter.TryFormat(contentLength, span, out var bytesWritten, _hexFormat)) - { - throw new NotSupportedException("Chunk size too large"); - } - Debug.Assert(chunkLengthHexDigitsLength == bytesWritten, "HEX formatting math problem."); - var headerLength = chunkLengthHexDigitsLength + 2; - - // Total chunk length: content length as HEX string + \r\n + content + \r\n - var spanOffset = headerLength + contentLength; - var chunkTotalLength = spanOffset + ChunkTerminator.Length; - - Debug.Assert(span.Length >= chunkTotalLength, "Bad chunk size calculation."); - - // Write out the chunk terminator - ChunkTerminator.CopyTo(span[spanOffset..]); - spanOffset = chunkTotalLength; - - if (!isFinal) - { - _output.Advance(chunkTotalLength); - StartNewChunk(sizeHint); - } - else - { - // Write out final chunk (zero-length chunk) - var terminator = "0\r\n\r\n"u8; - if ((spanOffset + terminator.Length) <= span.Length) - { - // There's space for the final chunk in the current span - terminator.CopyTo(span[spanOffset..]); - _output.Advance(chunkTotalLength + terminator.Length); - } - else - { - // Final chunk doesn't fit in current span so just write it directly after advancing the writer - _output.Advance(chunkTotalLength); - _output.Write(terminator); - } - } - - _buffered = 0; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(ReadOnlySpan source) - { - ThrowIfEnded(); - - if (_currentChunk.Length >= (source.Length + ChunkTerminator.Length)) - { - source.CopyTo(_currentChunk.Span); - Advance(source.Length); - } - else - { - WriteMultiBuffer(source); - } - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private void EnsureMore(int count = 0) - { - if (count > (_currentChunk.Length - _buffered - ChunkTerminator.Length)) - { - if (_buffered > 0) - { - CommitCurrentChunk(isFinal: false, count); - } - else - { - StartNewChunk(count); - } - } - } - - private void WriteMultiBuffer(ReadOnlySpan source) - { - while (source.Length > 0) - { - if ((_currentChunk.Length - ChunkTerminator.Length) == 0) - { - EnsureMore(); - } - - var writable = Math.Min(source.Length, _currentChunk.Length - ChunkTerminator.Length); - source[..writable].CopyTo(_currentChunk.Span); - source = source[writable..]; - Advance(writable); - } - } - - private void ThrowIfEnded() - { - if (_ended) - { - throw new InvalidOperationException("Cannot use the writer after calling End()."); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/AppSettings.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/AppSettings.cs deleted file mode 100644 index 38818920e16..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/AppSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public class AppSettings -{ - public string ConnectionString { get; set; } - - public DatabaseServer Database { get; set; } = DatabaseServer.None; -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/DatabaseServer.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/DatabaseServer.cs deleted file mode 100644 index 6d92dfbf82c..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Configuration/DatabaseServer.cs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public enum DatabaseServer -{ - None, - SqlServer, - PostgreSql, - MySql -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/BatchUpdateString.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/BatchUpdateString.cs deleted file mode 100644 index 72ff323850d..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/BatchUpdateString.cs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -internal sealed class BatchUpdateString -{ - private const int MaxBatch = 500; - - public static DatabaseServer DatabaseServer; - - internal static readonly string[] Ids = Enumerable.Range(0, MaxBatch).Select(i => $"@Id_{i}").ToArray(); - internal static readonly string[] Randoms = Enumerable.Range(0, MaxBatch).Select(i => $"@Random_{i}").ToArray(); - - private static readonly string[] _queries = new string[MaxBatch + 1]; - - public static string Query(int batchSize) - => _queries[batchSize] is null - ? CreateBatch(batchSize) - : _queries[batchSize]; - - private static string CreateBatch(int batchSize) - { - var sb = StringBuilderCache.Acquire(); - - if (DatabaseServer == DatabaseServer.PostgreSql) - { - sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES "); - var c = 1; - for (var i = 0; i < batchSize; i++) - { - if (i > 0) - sb.Append(", "); - sb.Append($"(${c++}, ${c++})"); - } - sb.Append(" ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id"); - } - else - { - Enumerable.Range(0, batchSize).ToList().ForEach(i => sb.Append($"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};")); - } - - return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/CachedWorld.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/CachedWorld.cs deleted file mode 100644 index fc59d5c17f0..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/CachedWorld.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public sealed class CachedWorld -{ - public int Id { get; set; } - - public int RandomNumber { get; set; } - - public static implicit operator CachedWorld(World world) => new() { Id = world.Id, RandomNumber = world.RandomNumber }; -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf16.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf16.cs deleted file mode 100644 index 74602be355f..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf16.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public readonly struct FortuneUtf16 : IComparable, IComparable -{ - public FortuneUtf16(int id, string message) - { - Id = id; - Message = message; - } - - public int Id { get; } - - public string Message { get; } - - public int CompareTo(object obj) => throw new InvalidOperationException("The non-generic CompareTo should not be used"); - - // Performance critical, using culture insensitive comparison - public int CompareTo(FortuneUtf16 other) => string.CompareOrdinal(Message, other.Message); -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf8.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf8.cs deleted file mode 100644 index a914f30539d..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/FortuneUtf8.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public readonly struct FortuneUtf8 : IComparable, IComparable -{ - public FortuneUtf8(int id, byte[] message) - { - Id = id; - Message = message; - } - - public int Id { get; } - - public byte[] Message { get; } - - public int CompareTo(object obj) => throw new InvalidOperationException("The non-generic CompareTo should not be used"); - - // Performance critical, using culture insensitive comparison - public int CompareTo(FortuneUtf8 other) => Message.AsSpan().SequenceCompareTo(other.Message.AsSpan()); -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/JsonMessage.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/JsonMessage.cs deleted file mode 100644 index 5bfe9115fe2..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/JsonMessage.cs +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -namespace PlatformBenchmarks; - -public struct JsonMessage -{ - public string message { get; set; } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbMySqlConnector.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbMySqlConnector.cs deleted file mode 100644 index 5b23c3b4c1f..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbMySqlConnector.cs +++ /dev/null @@ -1,272 +0,0 @@ -// 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 MYSQLCONNECTOR - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; -using MySqlConnector; - -namespace PlatformBenchmarks -{ - // Is semantically identical to RawDbNpgsql.cs. - // If you are changing RawDbMySqlConnector.cs, also consider changing RawDbNpgsql.cs. - public sealed class RawDb - { - private readonly ConcurrentRandom _random; - private readonly string _connectionString; - private readonly MemoryCache _cache = new( - new MemoryCacheOptions - { - ExpirationScanFrequency = TimeSpan.FromMinutes(60) - }); - - public RawDb(ConcurrentRandom random, AppSettings appSettings) - { - _random = random; - _connectionString = appSettings.ConnectionString; - } - - public async Task LoadSingleQueryRow() - { - using (var db = new MySqlConnection(_connectionString)) - { - await db.OpenAsync(); - - var (cmd, _) = await CreateReadCommandAsync(db); - using (cmd) - { - return await ReadSingleRow(cmd); - } - } - } - - public async Task LoadMultipleQueriesRows(int count) - { - var result = new World[count]; - - using (var db = new MySqlConnection(_connectionString)) - { - await db.OpenAsync(); - - var (cmd, idParameter) = await CreateReadCommandAsync(db); - using (cmd) - { - for (int i = 0; i < result.Length; i++) - { - result[i] = await ReadSingleRow(cmd); - idParameter.Value = _random.Next(1, 10001); - } - } - } - - return result; - } - - public Task LoadCachedQueries(int count) - { - var result = new CachedWorld[count]; - var cacheKeys = _cacheKeys; - var cache = _cache; - var random = _random; - for (var i = 0; i < result.Length; i++) - { - var id = random.Next(1, 10001); - var key = cacheKeys[id]; - if (cache.TryGetValue(key, out object cached)) - { - result[i] = (CachedWorld)cached; - } - else - { - return LoadUncachedQueries(id, i, count, this, result); - } - } - - return Task.FromResult(result); - - static async Task LoadUncachedQueries(int id, int i, int count, RawDb rawdb, CachedWorld[] result) - { - using (var db = new MySqlConnection(rawdb._connectionString)) - { - await db.OpenAsync(); - - var (cmd, idParameter) = await rawdb.CreateReadCommandAsync(db); - using (cmd) - { - Func> create = async _ => - { - return await rawdb.ReadSingleRow(cmd); - }; - - var cacheKeys = _cacheKeys; - var key = cacheKeys[id]; - - idParameter.Value = id; - - for (; i < result.Length; i++) - { - result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - - id = rawdb._random.Next(1, 10001); - idParameter.Value = id; - key = cacheKeys[id]; - } - } - } - - return result; - } - } - - public async Task PopulateCache() - { - using (var db = new MySqlConnection(_connectionString)) - { - await db.OpenAsync(); - - var (cmd, idParameter) = await CreateReadCommandAsync(db); - using (cmd) - { - var cacheKeys = _cacheKeys; - var cache = _cache; - for (var i = 1; i < 10001; i++) - { - idParameter.Value = i; - cache.Set(cacheKeys[i], await ReadSingleRow(cmd)); - } - } - } - - Console.WriteLine("Caching Populated"); - } - - public async Task LoadMultipleUpdatesRows(int count) - { - var results = new World[count]; - - using (var db = new MySqlConnection(_connectionString)) - { - await db.OpenAsync(); - - var (queryCmd, queryParameter) = await CreateReadCommandAsync(db); - using (queryCmd) - { - for (int i = 0; i < results.Length; i++) - { - results[i] = await ReadSingleRow(queryCmd); - queryParameter.Value = _random.Next(1, 10001); - } - } - - using (var updateCmd = new MySqlCommand(BatchUpdateString.Query(count), db)) - { - var ids = BatchUpdateString.Ids; - var randoms = BatchUpdateString.Randoms; - - for (int i = 0; i < results.Length; i++) - { - var randomNumber = _random.Next(1, 10001); - - updateCmd.Parameters.Add(new MySqlParameter(ids[i], results[i].Id)); - updateCmd.Parameters.Add(new MySqlParameter(randoms[i], randomNumber)); - - results[i].RandomNumber = randomNumber; - } - - await updateCmd.ExecuteNonQueryAsync(); - } - } - - return results; - } - - public async Task> LoadFortunesRows() - { - var result = new List(); - - using (var db = new MySqlConnection(_connectionString)) - { - await db.OpenAsync(); - - using (var cmd = new MySqlCommand("SELECT id, message FROM fortune", db)) - { - await cmd.PrepareAsync(); - - using (var rdr = await cmd.ExecuteReaderAsync()) - { - while (await rdr.ReadAsync()) - { - result.Add( - new FortuneUtf16 - ( - id: rdr.GetInt32(0), - message: rdr.GetString(1) - )); - } - } - } - } - - result.Add(new FortuneUtf16(id: 0, message: "Additional fortune added at request time." )); - result.Sort(); - - return result; - } - - private async Task<(MySqlCommand readCmd, MySqlParameter idParameter)> CreateReadCommandAsync(MySqlConnection connection) - { - var cmd = new MySqlCommand("SELECT id, randomnumber FROM world WHERE id = @Id", connection); - var parameter = new MySqlParameter("@Id", _random.Next(1, 10001)); - - cmd.Parameters.Add(parameter); - - await cmd.PrepareAsync(); - - return (cmd, parameter); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private async Task ReadSingleRow(MySqlCommand cmd) - { - using (var rdr = await cmd.ExecuteReaderAsync(System.Data.CommandBehavior.SingleRow)) - { - await rdr.ReadAsync(); - - return new World - { - Id = rdr.GetInt32(0), - RandomNumber = rdr.GetInt32(1) - }; - } - } - - private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select(i => new CacheKey(i)).ToArray(); - - public sealed class CacheKey : IEquatable - { - private readonly int _value; - - public CacheKey(int value) - => _value = value; - - public bool Equals(CacheKey key) - => key._value == _value; - - public override bool Equals(object obj) - => ReferenceEquals(obj, this); - - public override int GetHashCode() - => _value; - - public override string ToString() - => _value.ToString(); - } - } -} - -#endif \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbNpgsql.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbNpgsql.cs deleted file mode 100644 index 3bcb2a9a1e9..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Providers/RawDbNpgsql.cs +++ /dev/null @@ -1,269 +0,0 @@ -// 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 NPGSQL - -using System.Runtime.CompilerServices; -using Microsoft.Extensions.Caching.Memory; -using Npgsql; - -namespace PlatformBenchmarks -{ - // Is semantically identical to RawDbMySqlConnector.cs. - // If you are changing RawDbNpgsql.cs, also consider changing RawDbMySqlConnector.cs. - public sealed class RawDb - { - private readonly ConcurrentRandom _random; - private readonly MemoryCache _cache = new( - new MemoryCacheOptions - { - ExpirationScanFrequency = TimeSpan.FromMinutes(60) - }); - - private readonly NpgsqlDataSource _dataSource; - - public RawDb(ConcurrentRandom random, AppSettings appSettings) - { - _random = random; - _dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString); - } - - public async Task LoadSingleQueryRow() - { - using var db = _dataSource.CreateConnection(); - await db.OpenAsync(); - - var (cmd, _) = CreateReadCommand(db); - using var command = cmd; - return await ReadSingleRow(cmd); - } - - public async Task LoadMultipleQueriesRows(int count) - { - var results = new World[count]; - - using var connection = await _dataSource.OpenConnectionAsync(); - - using var batch = new NpgsqlBatch(connection) - { - // Inserts a PG Sync message between each statement in the batch, required for compliance with - // TechEmpower general test requirement 7 - // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview - EnableErrorBarriers = true - }; - - for (var i = 0; i < count; i++) - { - batch.BatchCommands.Add(new() - { - CommandText = "SELECT id, randomnumber FROM world WHERE id = $1", - Parameters = { new NpgsqlParameter { TypedValue = _random.Next(1, 10001) } } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); - } - - return results; - } - - public Task LoadCachedQueries(int count) - { - var result = new CachedWorld[count]; - var cacheKeys = _cacheKeys; - var cache = _cache; - var random = _random; - for (var i = 0; i < result.Length; i++) - { - var id = random.Next(1, 10001); - var key = cacheKeys[id]; - if (cache.TryGetValue(key, out var cached)) - { - result[i] = (CachedWorld)cached; - } - else - { - return LoadUncachedQueries(id, i, count, this, result); - } - } - - return Task.FromResult(result); - - static async Task LoadUncachedQueries(int id, int i, int count, RawDb rawdb, CachedWorld[] result) - { - using var db = rawdb._dataSource.CreateConnection(); - await db.OpenAsync(); - - var (cmd, idParameter) = rawdb.CreateReadCommand(db); - using var command = cmd; - async Task create(ICacheEntry _) => await ReadSingleRow(cmd); - - var cacheKeys = _cacheKeys; - var key = cacheKeys[id]; - - idParameter.TypedValue = id; - - for (; i < result.Length; i++) - { - result[i] = await rawdb._cache.GetOrCreateAsync(key, create); - - id = rawdb._random.Next(1, 10001); - idParameter.TypedValue = id; - key = cacheKeys[id]; - } - - return result; - } - } - - public async Task PopulateCache() - { - using var db = _dataSource.CreateConnection(); - await db.OpenAsync(); - - var (cmd, idParameter) = CreateReadCommand(db); - using var command = cmd; - var cacheKeys = _cacheKeys; - var cache = _cache; - for (var i = 1; i < 10001; i++) - { - idParameter.TypedValue = i; - cache.Set(cacheKeys[i], await ReadSingleRow(cmd)); - } - - Console.WriteLine("Caching Populated"); - } - - public async Task LoadMultipleUpdatesRows(int count) - { - var results = new World[count]; - - using var connection = _dataSource.CreateConnection(); - await connection.OpenAsync(); - - using (var batch = new NpgsqlBatch(connection)) - { - // Inserts a PG Sync message between each statement in the batch, required for compliance with - // TechEmpower general test requirement 7 - // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview - batch.EnableErrorBarriers = true; - - for (var i = 0; i < count; i++) - { - batch.BatchCommands.Add(new() - { - CommandText = "SELECT id, randomnumber FROM world WHERE id = $1", - Parameters = { new NpgsqlParameter { TypedValue = _random.Next(1, 10001) } } - }); - } - - using var reader = await batch.ExecuteReaderAsync(); - - for (var i = 0; i < count; i++) - { - await reader.ReadAsync(); - results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; - await reader.NextResultAsync(); - } - } - - using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection)) - { - for (int i = 0; i < results.Length; i++) - { - var randomNumber = _random.Next(1, 10001); - - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = results[i].Id }); - updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = randomNumber }); - - results[i].RandomNumber = randomNumber; - } - - await updateCmd.ExecuteNonQueryAsync(); - } - - return results; - } - - public async Task> LoadFortunesRows() - { - var result = new List(); - - using (var db = _dataSource.CreateConnection()) - { - await db.OpenAsync(); - - using var cmd = new NpgsqlCommand("SELECT id, message FROM fortune", db); - using var rdr = await cmd.ExecuteReaderAsync(); - while (await rdr.ReadAsync()) - { - result.Add(new FortuneUtf8 - ( - id:rdr.GetInt32(0), - message: rdr.GetFieldValue(1) - )); - } - } - - result.Add(new FortuneUtf8(id: 0, AdditionalFortune)); - result.Sort(); - - return result; - } - - private readonly byte[] AdditionalFortune = "Additional fortune added at request time."u8.ToArray(); - - private (NpgsqlCommand readCmd, NpgsqlParameter idParameter) CreateReadCommand(NpgsqlConnection connection) - { - var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection); - var parameter = new NpgsqlParameter { TypedValue = _random.Next(1, 10001) }; - - cmd.Parameters.Add(parameter); - - return (cmd, parameter); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static async Task ReadSingleRow(NpgsqlCommand cmd) - { - using var rdr = await cmd.ExecuteReaderAsync(System.Data.CommandBehavior.SingleRow); - await rdr.ReadAsync(); - - return new World - { - Id = rdr.GetInt32(0), - RandomNumber = rdr.GetInt32(1) - }; - } - - private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select(i => new CacheKey(i)).ToArray(); - - public sealed class CacheKey : IEquatable - { - private readonly int _value; - - public CacheKey(int value) - => _value = value; - - public bool Equals(CacheKey key) - => key._value == _value; - - public override bool Equals(object obj) - => ReferenceEquals(obj, this); - - public override int GetHashCode() - => _value; - - public override string ToString() - => _value.ToString(); - } - } -} - -#endif diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Random.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Random.cs deleted file mode 100644 index 520500157b2..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/Random.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -using System.Runtime.CompilerServices; - -namespace PlatformBenchmarks; - -public sealed class ConcurrentRandom -{ - private static int nextSeed = 0; - - // Random isn't thread safe - [ThreadStatic] - private static Random _random; - - private static Random Random => _random ?? CreateRandom(); - - [MethodImpl(MethodImplOptions.NoInlining)] - private static Random CreateRandom() - { - _random = new Random(Interlocked.Increment(ref nextSeed)); - return _random; - } - - public int Next(int minValue, int maxValue) - { - return Random.Next(minValue, maxValue); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/World.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/World.cs deleted file mode 100644 index 89ba3ea87bf..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/World.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -using System.Runtime.InteropServices; - -namespace PlatformBenchmarks; - -[StructLayout(LayoutKind.Sequential, Size = 8)] -public struct World -{ - public int Id { get; set; } - - public int RandomNumber { get; set; } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/DateHeader.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/DateHeader.cs deleted file mode 100644 index 99cfdc8f0a6..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/DateHeader.cs +++ /dev/null @@ -1,60 +0,0 @@ -// 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. - -using System.Buffers.Text; -using System.Diagnostics; -using System.Text; - -namespace PlatformBenchmarks; - -/// -/// Manages the generation of the date header value. -/// -internal static class DateHeader -{ - const int prefixLength = 8; // "\r\nDate: ".Length - const int dateTimeRLength = 29; // Wed, 14 Mar 2018 14:20:00 GMT - const int suffixLength = 2; // crlf - const int suffixIndex = dateTimeRLength + prefixLength; - - private static readonly Timer s_timer = new(_ => SetDateValues(DateTimeOffset.UtcNow), null, 1000, 1000); - - private static byte[] s_headerBytesMaster = new byte[prefixLength + dateTimeRLength + 2 * suffixLength]; - private static byte[] s_headerBytesScratch = new byte[prefixLength + dateTimeRLength + 2 * suffixLength]; - - static DateHeader() - { - var utf8 = "\r\nDate: "u8; - - utf8.CopyTo(s_headerBytesMaster); - utf8.CopyTo(s_headerBytesScratch); - s_headerBytesMaster[suffixIndex] = (byte)'\r'; - s_headerBytesMaster[suffixIndex + 1] = (byte)'\n'; - s_headerBytesMaster[suffixIndex + 2] = (byte)'\r'; - s_headerBytesMaster[suffixIndex + 3] = (byte)'\n'; - s_headerBytesScratch[suffixIndex] = (byte)'\r'; - s_headerBytesScratch[suffixIndex + 1] = (byte)'\n'; - s_headerBytesScratch[suffixIndex + 2] = (byte)'\r'; - s_headerBytesScratch[suffixIndex + 3] = (byte)'\n'; - - SetDateValues(DateTimeOffset.UtcNow); - SyncDateTimer(); - } - - public static void SyncDateTimer() => s_timer.Change(1000, 1000); - - public static ReadOnlySpan HeaderBytes => s_headerBytesMaster; - - private static void SetDateValues(DateTimeOffset value) - { - lock (s_headerBytesScratch) - { - if (!Utf8Formatter.TryFormat(value, s_headerBytesScratch.AsSpan(prefixLength), out var written, 'R')) - { - throw new Exception("date time format failed"); - } - Debug.Assert(written == dateTimeRLength); - (s_headerBytesScratch, s_headerBytesMaster) = (s_headerBytesMaster, s_headerBytesScratch); - } - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/HttpApplication.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/HttpApplication.cs deleted file mode 100644 index d82368e15a3..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/HttpApplication.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -using System.Threading.Tasks; -using Microsoft.AspNetCore.Connections; - -namespace PlatformBenchmarks; - -public static class HttpApplicationConnectionBuilderExtensions -{ - public static IConnectionBuilder UseHttpApplication