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("Fortunes"); - foreach (var item in model) - { - sb.Append(""); - } - - sb.Append("
idmessage
"); - sb.Append(item.Id.ToString(CultureInfo.InvariantCulture)); - sb.Append(""); - sb.Append(htmlEncoder.Encode(item.Message)); - 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 - - @foreach (var item in Model) - { - - } -
idmessage
@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(this IConnectionBuilder builder) where TConnection : IHttpConnection, new() - { - return builder.Use(next => new HttpApplication().ExecuteAsync); - } -} - -public sealed class HttpApplication where TConnection : IHttpConnection, new() -{ - public Task ExecuteAsync(ConnectionContext connection) - { - var httpConnection = new TConnection - { - Reader = connection.Transport.Input, - Writer = connection.Transport.Output - }; - return httpConnection.ExecuteAsync(); - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/IHttpConnection.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/IHttpConnection.cs deleted file mode 100644 index d2dee82255b..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/IHttpConnection.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.IO.Pipelines; -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; - -namespace PlatformBenchmarks; - -public interface IHttpConnection : IHttpHeadersHandler, IHttpRequestLineHandler -{ - PipeReader Reader { get; set; } - PipeWriter Writer { get; set; } - Task ExecuteAsync(); -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/NuGet.Config b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/NuGet.Config deleted file mode 100644 index f05d5867888..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/NuGet.Config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/PlatformBenchmarks.csproj b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/PlatformBenchmarks.csproj deleted file mode 100644 index 0a68f121bde..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/PlatformBenchmarks.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - net7.0 - Exe - true - enable - - - true - - - true - Speed - true - x86-x64-v3 - - - - $(DefineConstants);DATABASE - $(DefineConstants);NPGSQL - $(DefineConstants);MYSQLCONNECTOR - - - - - - - - - - - - diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Program.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Program.cs deleted file mode 100644 index 79b8d7de6de..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Program.cs +++ /dev/null @@ -1,109 +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; -using System.Text; - -namespace PlatformBenchmarks; - -public sealed class Program -{ - public static string[] Args; - - public static async Task Main(string[] args) - { - Args = args; - -#if NPGSQL - // This disables SQL parsing/rewriting, which requires using positional parameters and NpgsqlBatch everywhere. - // This helps commands where there are no parameters (Fortunes); when there are parameters, their ParameterName - // being null already triggers positional parameters and disables parsing) - // Note that Dapper and EF aren't yet compatible with this mode. - AppContext.SetSwitch("Npgsql.EnableSqlRewriting", false); -#endif - - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.ApplicationName)); -#if !DATABASE - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.Plaintext)); - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.Json)); -#else - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.Fortunes)); - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.SingleQuery)); - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.Updates)); - Console.WriteLine(Encoding.UTF8.GetString(BenchmarkApplication.Paths.MultipleQueries)); -#endif - DateHeader.SyncDateTimer(); - - var host = BuildWebHost(args); - var config = (IConfiguration)host.Services.GetService(typeof(IConfiguration)); - BatchUpdateString.DatabaseServer = config.Get().Database; -#if DATABASE - try - { - await BenchmarkApplication.Db.PopulateCache(); - } - catch (Exception ex) - { - Console.WriteLine($"Error trying to populate database cache: {ex}"); - } -#endif - await host.RunAsync(); - } - - public static IWebHost BuildWebHost(string[] args) - { - var config = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") -#if DEBUG - .AddUserSecrets() -#endif - .AddEnvironmentVariables() - .AddEnvironmentVariables(prefix: "ASPNETCORE_") - .AddCommandLine(args) - .Build(); - - var appSettings = config.Get(); -#if DATABASE - Console.WriteLine($"Database: {appSettings.Database}"); - Console.WriteLine($"ConnectionString: {appSettings.ConnectionString}"); - - if (appSettings.Database is DatabaseServer.PostgreSql - or DatabaseServer.MySql) - { - BenchmarkApplication.Db = new RawDb(new ConcurrentRandom(), appSettings); - } - else - { - throw new NotSupportedException($"{appSettings.Database} is not supported"); - } -#endif - - var hostBuilder = new WebHostBuilder() - .UseBenchmarksConfiguration(config) - .UseKestrel((context, options) => - { - var endPoint = context.Configuration.CreateIPEndPoint(); - - options.Listen(endPoint, builder => - { - builder.UseHttpApplication(); - }); - }) - .UseStartup(); - - hostBuilder.UseSockets(options => - { - options.WaitForDataBeforeAllocatingBuffer = false; - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - options.UnsafePreferInlineScheduling = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS") == "1"; - } - }); - - - var host = hostBuilder.Build(); - - return host; - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Startup.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Startup.cs deleted file mode 100644 index 069fe381a42..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Startup.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 sealed class Startup -{ - public void Configure(IApplicationBuilder app) - { - } -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/StringBuilderCache.cs b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/StringBuilderCache.cs deleted file mode 100644 index d1d6c69d354..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/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 PlatformBenchmarks; - -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/PlatformBenchmarks/Templates/FortunesUtf16.cshtml b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/FortunesUtf16.cshtml deleted file mode 100644 index a721e3044ce..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/FortunesUtf16.cshtml +++ /dev/null @@ -1,2 +0,0 @@ -@inherits RazorSlice> -Fortunes@foreach (var item in Model){}
idmessage
@item.Id@item.Message
\ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/FortunesUtf8.cshtml b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/FortunesUtf8.cshtml deleted file mode 100644 index 4288f407b70..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/FortunesUtf8.cshtml +++ /dev/null @@ -1,2 +0,0 @@ -@inherits RazorSlice> -Fortunes@foreach (var item in Model){}
idmessage
@item.Id@item.Message
\ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/_ViewImports.cshtml b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/_ViewImports.cshtml deleted file mode 100644 index 7cda0a3015e..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Templates/_ViewImports.cshtml +++ /dev/null @@ -1,9 +0,0 @@ -@inherits RazorSlice - -@using System.Globalization; -@using Microsoft.AspNetCore.Razor; -@using RazorSlices; -@using PlatformBenchmarks; - -@tagHelperPrefix __disable_tagHelpers__: -@removeTagHelper *, Microsoft.AspNetCore.Mvc.Razor \ No newline at end of file diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.json b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.json deleted file mode 100644 index 2fa97145aaa..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ConnectionString": "Server=localhost;Database=fortunes;User Id=test;Password=test", - "Database": "PostgreSQL" -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.mysql.json b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.mysql.json deleted file mode 100644 index 5db959976d2..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.mysql.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;SslMode=None;ConnectionReset=false;ConnectionIdlePingTime=900;ConnectionIdleTimeout=0;AutoEnlist=false;DefaultCommandTimeout=0;ConnectionTimeout=0;IgnorePrepare=false;", - "Database": "mysql" -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.json b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.json deleted file mode 100644 index 48ba2b683ff..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000", - "Database": "postgresql" -} diff --git a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.updates.json b/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.updates.json deleted file mode 100644 index 83e94d7c745..00000000000 --- a/frameworks/CSharp/aspnetcore/PlatformBenchmarks/appsettings.postgresql.updates.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000", - "Database": "postgresql" -} diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs index 671ee726ec7..cbd375cb61b 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs @@ -41,42 +41,11 @@ public async Task ExecuteAsync() } } - 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; - } - private async Task ProcessRequestsAsync() { while (true) { - var readResult = await Reader.ReadAsync(default); + var readResult = await Reader.ReadAsync(); var buffer = readResult.Buffer; var isCompleted = readResult.IsCompleted; @@ -85,35 +54,23 @@ private async Task ProcessRequestsAsync() return; } - if (!HandleRequests(buffer, isCompleted)) + if (!HandleRequests(ref buffer, isCompleted)) { - await ProcessRequestAsync(); + await HandleRequestAsync(buffer); } - - await Writer.FlushAsync(default); + + await Writer.FlushAsync(); } } - private bool HandleRequests(in ReadOnlySequence buffer, bool isCompleted) + private bool HandleRequests(ref ReadOnlySequence buffer, bool isCompleted) { var reader = new SequenceReader(buffer); - var hasWriter = false; - BufferWriter writer = default; + 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; - } - - // Only create the local writer if the request is Plaintext or Json - - if (!hasWriter) - { - hasWriter = true; - writer = GetWriter(Writer, sizeHint: 160 * 16); // 160*16 is for Plaintext, for Json 160 would be enough - } + ParseHttpRequest(ref reader, ref buffer, isCompleted); if (_state == State.Body) { @@ -136,12 +93,65 @@ private bool HandleRequests(in ReadOnlySequence buffer, bool isCompleted) break; } - if (hasWriter) - { - writer.Commit(); + writer.Commit(); + return true; + } + + private async Task HandleRequestAsync(ReadOnlySequence buffer) + { + if (_state == State.Body) + { + await ProcessRequestAsync(); + + _state = State.StartLine; } - return true; + // No more input or incomplete data, Advance the Reader + Reader.AdvanceTo(buffer.Start, buffer.End); + } + + private void ParseHttpRequest(ref SequenceReader reader, ref ReadOnlySequence buffer, 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; + + if (_requestType != RequestType.Json && _requestType != RequestType.PlainText) + { + 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); + } + } } private static HtmlEncoder CreateHtmlEncoder() diff --git a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs index a01ce73a9f5..1d7810c2ebc 100644 --- a/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs +++ b/frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs @@ -143,16 +143,6 @@ private static int ParseQueries(ReadOnlySpan parameter) return queries; } - private Task ProcessRequestAsync() => _requestType switch - { - RequestType.FortunesRaw => FortunesRaw(Writer), - RequestType.SingleQuery => SingleQuery(Writer), - RequestType.Caching => Caching(Writer, _queries), - RequestType.Updates => Updates(Writer, _queries), - RequestType.MultipleQueries => MultipleQueries(Writer, _queries), - _ => Default(Writer) - }; - private bool ProcessRequest(ref BufferWriter writer) { if (_requestType == RequestType.PlainText) @@ -171,6 +161,16 @@ private bool ProcessRequest(ref BufferWriter writer) return true; } + private Task ProcessRequestAsync() => _requestType switch + { + RequestType.FortunesRaw => FortunesRaw(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); @@ -181,8 +181,8 @@ private static Task Default(PipeWriter pipeWriter) private static ReadOnlySpan _defaultPreamble => "HTTP/1.1 200 OK\r\n"u8 + - "Server: K"u8 + "\r\n"u8 + - "Content-Type: text/plain"u8 + + "Server: K\r\n"u8 + + "Content-Type: text/plain\r\n"u8 + "Content-Length: 0"u8; private static void Default(ref BufferWriter writer) diff --git a/frameworks/Go/aah/src/benchmark/app/models/models.go b/frameworks/Go/aah/src/benchmark/app/models/models.go index a0bb9681158..1c79d855228 100644 --- a/frameworks/Go/aah/src/benchmark/app/models/models.go +++ b/frameworks/Go/aah/src/benchmark/app/models/models.go @@ -80,7 +80,7 @@ func MySQLFortunes() (Fortunes, error) { return nil, err } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { var fortune Fortune if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil { @@ -156,7 +156,7 @@ func PGFortunes() (Fortunes, error) { return nil, err } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { var fortune Fortune if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/atreugo/src/templates/fortune.go b/frameworks/Go/atreugo/src/templates/fortune.go index 4462132572e..aed21662e51 100644 --- a/frameworks/Go/atreugo/src/templates/fortune.go +++ b/frameworks/Go/atreugo/src/templates/fortune.go @@ -15,7 +15,7 @@ var ( fortunesPool = sync.Pool{ New: func() interface{} { return &Fortunes{ - F: make([]Fortune, 0, 16), + F: make([]Fortune, 0), } }, } diff --git a/frameworks/Go/chi/src/chi-gojay/server.go b/frameworks/Go/chi/src/chi-gojay/server.go index 582a6c71229..c65e65cdb09 100644 --- a/frameworks/Go/chi/src/chi-gojay/server.go +++ b/frameworks/Go/chi/src/chi-gojay/server.go @@ -132,7 +132,7 @@ func fortunes(w http.ResponseWriter, r *http.Request) { return } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/chi/src/chi-sjson/server.go b/frameworks/Go/chi/src/chi-sjson/server.go index 582a6c71229..c65e65cdb09 100644 --- a/frameworks/Go/chi/src/chi-sjson/server.go +++ b/frameworks/Go/chi/src/chi-sjson/server.go @@ -132,7 +132,7 @@ func fortunes(w http.ResponseWriter, r *http.Request) { return } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/chi/src/chi/server.go b/frameworks/Go/chi/src/chi/server.go index 582a6c71229..c65e65cdb09 100644 --- a/frameworks/Go/chi/src/chi/server.go +++ b/frameworks/Go/chi/src/chi/server.go @@ -132,7 +132,7 @@ func fortunes(w http.ResponseWriter, r *http.Request) { return } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/clevergo/main.go b/frameworks/Go/clevergo/main.go index 9b92c2e9510..0b3d9819f3a 100644 --- a/frameworks/Go/clevergo/main.go +++ b/frameworks/Go/clevergo/main.go @@ -171,7 +171,7 @@ func fortunesHandler(c *clevergo.Context) error { } defer rows.Close() - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { // Fetch rows f := new(Fortune) if err := rows.Scan(&f.ID, &f.Message); err != nil { diff --git a/frameworks/Go/echo/src/main.go b/frameworks/Go/echo/src/main.go index 5285cd27d51..ed999f215c0 100644 --- a/frameworks/Go/echo/src/main.go +++ b/frameworks/Go/echo/src/main.go @@ -242,7 +242,7 @@ func getQueryCount(q string) int { } func fetchFortunes(rows *sql.Rows) (Fortunes, error) { - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { // Fetch rows f := new(Fortune) if err := rows.Scan(&f.ID, &f.Message); err != nil { diff --git a/frameworks/Go/fasthttp/src/templates/fortune.go b/frameworks/Go/fasthttp/src/templates/fortune.go index 4462132572e..aed21662e51 100644 --- a/frameworks/Go/fasthttp/src/templates/fortune.go +++ b/frameworks/Go/fasthttp/src/templates/fortune.go @@ -15,7 +15,7 @@ var ( fortunesPool = sync.Pool{ New: func() interface{} { return &Fortunes{ - F: make([]Fortune, 0, 16), + F: make([]Fortune, 0), } }, } diff --git a/frameworks/Go/fiber/src/server.go b/frameworks/Go/fiber/src/server.go index b290f9cd53d..c592ccd3170 100644 --- a/frameworks/Go/fiber/src/server.go +++ b/frameworks/Go/fiber/src/server.go @@ -219,7 +219,7 @@ func templateHandler(c *fiber.Ctx) error { rows, _ := db.Query(context.Background(), fortuneselectsql) var f templates.Fortune - fortunes := make([]templates.Fortune, 0, 16) + fortunes := make([]templates.Fortune, 0) for rows.Next() { _ = rows.Scan(&f.ID, &f.Message) fortunes = append(fortunes, f) diff --git a/frameworks/Go/fiber/src/templates/fortune.go b/frameworks/Go/fiber/src/templates/fortune.go index 53dae5086ec..1d41ca2c80d 100644 --- a/frameworks/Go/fiber/src/templates/fortune.go +++ b/frameworks/Go/fiber/src/templates/fortune.go @@ -24,7 +24,7 @@ var fortunePool = &sync.Pool{ var fortunesPool = &sync.Pool{ New: func() interface{} { return &Fortunes{ - F: make([]Fortune, 0, 16), + F: make([]Fortune, 0), } }, } diff --git a/frameworks/Go/gearbox/src/main.go b/frameworks/Go/gearbox/src/main.go index ec5146b0ee4..5e933cf4421 100644 --- a/frameworks/Go/gearbox/src/main.go +++ b/frameworks/Go/gearbox/src/main.go @@ -200,7 +200,7 @@ func templateHandler(ctx gearbox.Context) { rows, _ := db.Query(context.Background(), fortuneselectsql) var f templates.Fortune - fortunes := make([]templates.Fortune, 0, 16) + fortunes := make([]templates.Fortune, 0) for rows.Next() { _ = rows.Scan(&f.ID, &f.Message) fortunes = append(fortunes, f) diff --git a/frameworks/Go/gearbox/src/templates/fortune.go b/frameworks/Go/gearbox/src/templates/fortune.go index 53dae5086ec..1d41ca2c80d 100644 --- a/frameworks/Go/gearbox/src/templates/fortune.go +++ b/frameworks/Go/gearbox/src/templates/fortune.go @@ -24,7 +24,7 @@ var fortunePool = &sync.Pool{ var fortunesPool = &sync.Pool{ New: func() interface{} { return &Fortunes{ - F: make([]Fortune, 0, 16), + F: make([]Fortune, 0), } }, } diff --git a/frameworks/Go/gin/gin-src/hello.go b/frameworks/Go/gin/gin-src/hello.go index ac00155adb1..88328c39e4b 100644 --- a/frameworks/Go/gin/gin-src/hello.go +++ b/frameworks/Go/gin/gin-src/hello.go @@ -61,12 +61,12 @@ func parseQueries(c *gin.Context) int { return n } -/// Test 1: JSON serialization +// / Test 1: JSON serialization func json(c *gin.Context) { c.JSON(200, gin.H{"message": "Hello, World!"}) } -/// Test 2: Single database query +// / Test 2: Single database query func db(c *gin.Context) { var world World err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber) @@ -77,7 +77,7 @@ func db(c *gin.Context) { c.JSON(200, &world) } -/// Test 3: Multiple database queries +// / Test 3: Multiple database queries func dbs(c *gin.Context) { numQueries := parseQueries(c) @@ -92,7 +92,7 @@ func dbs(c *gin.Context) { c.JSON(200, &worlds) } -/// Test 4: Fortunes +// / Test 4: Fortunes func fortunes(c *gin.Context) { rows, err := fortuneStatement.Query() if err != nil { @@ -100,7 +100,7 @@ func fortunes(c *gin.Context) { return } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil { @@ -115,7 +115,7 @@ func fortunes(c *gin.Context) { c.HTML(200, "fortune.html", fortunes) } -/// Test 5: Database updates +// / Test 5: Database updates func update(c *gin.Context) { numQueries := parseQueries(c) world := make([]World, numQueries) @@ -133,7 +133,7 @@ func update(c *gin.Context) { c.JSON(200, world) } -/// Test 6: plaintext +// / Test 6: plaintext func plaintext(c *gin.Context) { c.String(200, "Hello, World!") } diff --git a/frameworks/Go/gin/gin-std/main.go b/frameworks/Go/gin/gin-std/main.go index c8ab66e402d..43065bc9b22 100644 --- a/frameworks/Go/gin/gin-std/main.go +++ b/frameworks/Go/gin/gin-std/main.go @@ -61,12 +61,12 @@ func parseQueries(c *gin.Context) int { return n } -/// Test 1: JSON serialization +// / Test 1: JSON serialization func json(c *gin.Context) { c.JSON(200, gin.H{"message": "Hello, World!"}) } -/// Test 2: Single database query +// / Test 2: Single database query func db(c *gin.Context) { var world World err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber) @@ -77,7 +77,7 @@ func db(c *gin.Context) { c.JSON(200, &world) } -/// Test 3: Multiple database queries +// / Test 3: Multiple database queries func dbs(c *gin.Context) { numQueries := parseQueries(c) @@ -92,7 +92,7 @@ func dbs(c *gin.Context) { c.JSON(200, &worlds) } -/// Test 4: Fortunes +// / Test 4: Fortunes func fortunes(c *gin.Context) { rows, err := fortuneStatement.Query() if err != nil { @@ -100,7 +100,7 @@ func fortunes(c *gin.Context) { return } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil { @@ -115,7 +115,7 @@ func fortunes(c *gin.Context) { c.HTML(200, "fortune.html", fortunes) } -/// Test 5: Database updates +// / Test 5: Database updates func update(c *gin.Context) { numQueries := parseQueries(c) world := make([]World, numQueries) @@ -133,7 +133,7 @@ func update(c *gin.Context) { c.JSON(200, world) } -/// Test 6: plaintext +// / Test 6: plaintext func plaintext(c *gin.Context) { c.String(200, "Hello, World!") } diff --git a/frameworks/Go/go-std/src/storage/mgo.go b/frameworks/Go/go-std/src/storage/mgo.go index 88840312d68..8d7cc6eec4c 100644 --- a/frameworks/Go/go-std/src/storage/mgo.go +++ b/frameworks/Go/go-std/src/storage/mgo.go @@ -66,7 +66,7 @@ func (mongo Mongo) UpdateWorlds(selectedWorlds []World) error { // GetFortunes finds all fortunes from table func (mongo Mongo) GetFortunes() ([]templates.Fortune, error) { - fortunes := make([]templates.Fortune, 0, 16) + fortunes := make([]templates.Fortune, 0) if err := mongo.fortunes.Find(nil).All(&fortunes); err != nil { return nil, err diff --git a/frameworks/Go/go-std/src/storage/mysql.go b/frameworks/Go/go-std/src/storage/mysql.go index 02c9777886d..be003c00947 100644 --- a/frameworks/Go/go-std/src/storage/mysql.go +++ b/frameworks/Go/go-std/src/storage/mysql.go @@ -101,7 +101,7 @@ func (mysql MySQL) GetFortunes() ([]templates.Fortune, error) { return nil, fmt.Errorf("can't query fortunes: %s", err) } - fortunes := make([]templates.Fortune, 0, 16) + fortunes := make([]templates.Fortune, 0) var fortune templates.Fortune for rows.Next() { if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/go-std/src/storage/pgx.go b/frameworks/Go/go-std/src/storage/pgx.go index 8887e61c6f3..7e272cc5676 100644 --- a/frameworks/Go/go-std/src/storage/pgx.go +++ b/frameworks/Go/go-std/src/storage/pgx.go @@ -118,7 +118,7 @@ func (psql PGX) GetFortunes() ([]templates.Fortune, error) { return nil, fmt.Errorf("can't query fortunes: %s", err) } - fortunes := make([]templates.Fortune, 0, 16) + fortunes := make([]templates.Fortune, 0) var fortune templates.Fortune for rows.Next() { if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/go-std/src/storage/pq.go b/frameworks/Go/go-std/src/storage/pq.go index 5505d15e386..f0c416d2b26 100644 --- a/frameworks/Go/go-std/src/storage/pq.go +++ b/frameworks/Go/go-std/src/storage/pq.go @@ -109,7 +109,7 @@ package storage // return nil, fmt.Errorf("can't query fortunes: %s", err) // } -// fortunes := make([]templates.Fortune, 0, 16) +// fortunes := make([]templates.Fortune, 0) // var fortune templates.Fortune // for rows.Next() { // if err = rows.Scan(&fortune.ID, &fortune.Message); err != nil { diff --git a/frameworks/Go/go-std/src/templates/fortune.go b/frameworks/Go/go-std/src/templates/fortune.go index 84162e39eb7..fe7d16e5675 100644 --- a/frameworks/Go/go-std/src/templates/fortune.go +++ b/frameworks/Go/go-std/src/templates/fortune.go @@ -50,7 +50,7 @@ var FortunesPool *sync.Pool func InitFortunesPool() { FortunesPool = &sync.Pool{ New: func() interface{} { - return make([]Fortune, 0, 16) + return make([]Fortune, 0) }, } } diff --git a/frameworks/Go/goframe/src/template/fortune.go b/frameworks/Go/goframe/src/template/fortune.go index d23b2400ebc..fe443cb4a7d 100644 --- a/frameworks/Go/goframe/src/template/fortune.go +++ b/frameworks/Go/goframe/src/template/fortune.go @@ -15,7 +15,7 @@ var ( fortunesPool = sync.Pool{ New: func() interface{} { return &Fortunes{ - F: make([]Fortune, 0, 16), + F: make([]Fortune, 0), } }, } diff --git a/frameworks/Go/goji/src/goji/server.go b/frameworks/Go/goji/src/goji/server.go index 3456ffc9167..3fb6e09569e 100644 --- a/frameworks/Go/goji/src/goji/server.go +++ b/frameworks/Go/goji/src/goji/server.go @@ -37,7 +37,7 @@ var ( // Templates tmpl = template.Must(template. ParseFiles("templates/layout.html", - "templates/fortune.html")) + "templates/fortune.html")) // Database worldStatement *sql.Stmt @@ -146,7 +146,7 @@ func fortunes(c web.C, w http.ResponseWriter, r *http.Request) { log.Fatalf("Error preparing statement: %v", err) } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { fortune := Fortune{} diff --git a/frameworks/Go/hertz/benchmark_config.json b/frameworks/Go/hertz/benchmark_config.json index 77fd1d19e98..57cf3aa5d04 100644 --- a/frameworks/Go/hertz/benchmark_config.json +++ b/frameworks/Go/hertz/benchmark_config.json @@ -11,7 +11,7 @@ "port": 8080, "approach": "Realistic", "classification": "Micro", - "database": "MySQL", + "database": "Postgres", "framework": "hertz", "language": "Go", "flavor": "None", @@ -31,7 +31,7 @@ "port": 8080, "approach": "Realistic", "classification": "Fullstack", - "database": "postgres", + "database": "Postgres", "framework": "hertz-gorm", "language": "Go", "flavor": "None", diff --git a/frameworks/Go/hertz/config.toml b/frameworks/Go/hertz/config.toml index b359b65b6ed..400d6d85090 100644 --- a/frameworks/Go/hertz/config.toml +++ b/frameworks/Go/hertz/config.toml @@ -10,7 +10,7 @@ urls.update = "/update?queries=" urls.fortune = "/fortunes" approach = "Realistic" classification = "Micro" -database = "MySQL" +database = "Postgres" database_os = "Linux" os = "Linux" orm = "Raw" diff --git a/frameworks/Go/hertz/go.mod b/frameworks/Go/hertz/go.mod index cdf1e7713c6..a43ab903201 100644 --- a/frameworks/Go/hertz/go.mod +++ b/frameworks/Go/hertz/go.mod @@ -1,31 +1,36 @@ module hertz -go 1.18 +go 1.20 require ( - github.com/cloudwego/hertz v0.4.0 - github.com/go-sql-driver/mysql v1.6.0 + github.com/cloudwego/hertz v0.7.1 + github.com/goccy/go-json v0.10.2 + github.com/jackc/pgx/v5 v5.4.3 ) require ( github.com/bytedance/go-tagexpr/v2 v2.9.2 // indirect github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 // indirect - github.com/bytedance/sonic v1.5.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect - github.com/cloudwego/netpoll v0.2.6 // indirect + github.com/bytedance/sonic v1.8.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/cloudwego/netpoll v0.5.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/golang/protobuf v1.5.0 // indirect github.com/henrylee2cn/ameda v1.4.10 // indirect github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/nyaruka/phonenumbers v1.0.55 // indirect - github.com/stretchr/testify v1.7.1 // indirect - github.com/tidwall/gjson v1.13.0 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/yaml.v3 v3.0.0 // indirect ) diff --git a/frameworks/Go/hertz/go.sum b/frameworks/Go/hertz/go.sum new file mode 100644 index 00000000000..fb87f4188a7 --- /dev/null +++ b/frameworks/Go/hertz/go.sum @@ -0,0 +1,106 @@ +github.com/bytedance/go-tagexpr/v2 v2.9.2 h1:QySJaAIQgOEDQBLS3x9BxOWrnhqu5sQ+f6HaZIxD39I= +github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 h1:PtwsQyQJGxf8iaPptPNaduEIu9BnrNms+pcRdHAxZaM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q= +github.com/bytedance/mockey v1.2.1 h1:g84ngI88hz1DR4wZTL3yOuqlEcq67MretBfQUdXwrmw= +github.com/bytedance/mockey v1.2.1/go.mod h1:+Jm/fzWZAuhEDrPXVjDf/jLM2BlLXJkwk94zf2JZ3X4= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.1 h1:NqAHCaGaTzro0xMmnTCLUyRlbEP6r8MCA1cJUrH3Pu4= +github.com/bytedance/sonic v1.8.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/cloudwego/hertz v0.7.1 h1:4M8l4zvAE6yNxzfozpxHLMnRSRRPslKNw/McH5/qFns= +github.com/cloudwego/hertz v0.7.1/go.mod h1:WliNtVbwihWHHgAaIQEbVXl0O3aWj0ks1eoPrcEAnjs= +github.com/cloudwego/netpoll v0.5.0 h1:oRrOp58cPCvK2QbMozZNDESvrxQaEHW2dCimmwH1lcU= +github.com/cloudwego/netpoll v0.5.0/go.mod h1:xVefXptcyheopwNDZjDPcfU6kIjZXZ4nY550k1yH9eQ= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/henrylee2cn/ameda v1.4.8/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/ameda v1.4.10 h1:JdvI2Ekq7tapdPsuhrc4CaFiqw6QXFvZIULWJgQyCAk= +github.com/henrylee2cn/ameda v1.4.10/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 h1:yE9ULgp02BhYIrO6sdV/FPe0xQM6fNHkVQW2IAymfM0= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8/go.mod h1:Nhe/DM3671a5udlv2AdV2ni/MZzgfv2qrPL5nIi3EGQ= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg= +github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/frameworks/Go/hertz/hello.go b/frameworks/Go/hertz/hello.go index d7afe8f76ee..4df97c5a8eb 100644 --- a/frameworks/Go/hertz/hello.go +++ b/frameworks/Go/hertz/hello.go @@ -5,31 +5,45 @@ import ( "fmt" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" + "github.com/cloudwego/hertz/pkg/app/server/render" "github.com/cloudwego/hertz/pkg/common/config" - "github.com/cloudwego/hertz/pkg/common/utils" - "log" + "github.com/cloudwego/hertz/pkg/protocol" + "github.com/cloudwego/hertz/pkg/protocol/consts" + "github.com/goccy/go-json" + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" "math/rand" "runtime" "sort" - "strconv" - - "database/sql" + "sync" + "unsafe" +) - _ "github.com/go-sql-driver/mysql" +var ( + db *pgxpool.Pool ) const ( // Database - worldSelect = "SELECT id, randomNumber FROM World WHERE id = ?" - worldUpdate = "UPDATE World SET randomNumber = ? WHERE id = ?" - fortuneSelect = "SELECT id, message FROM Fortune;" - worldRowCount = 10000 - maxConnectionCount = 256 + helloworld = "Hello, World!" + worldSelect = "SELECT id, randomNumber FROM World WHERE id = $1" + worldUpdate = "UPDATE World SET randomNumber = $1 WHERE id = $2" + fortuneSelect = "SELECT id, message FROM Fortune;" + + worldRowCount = 10000 + jsonpath = "/json" + dbpath = "/db" + dbspath = "/dbs" + fortunespath = "/fortunes" + updatepath = "/update" + plaintextpath = "/plaintext" ) +var helloworldRaw = []byte("Hello, World!") + type World struct { - Id uint16 `json:"id"` - RandomNumber uint16 `json:"randomNumber"` + Id int32 `json:"id"` + RandomNumber int32 `json:"randomNumber"` } type Fortune struct { @@ -38,6 +52,7 @@ type Fortune struct { } type Fortunes []*Fortune +type Worlds []World func (s Fortunes) Len() int { return len(s) } func (s Fortunes) Swap(i, j int) { s[i], s[j] = s[j], s[i] } @@ -46,18 +61,9 @@ type ByMessage struct{ Fortunes } func (s ByMessage) Less(i, j int) bool { return s.Fortunes[i].Message < s.Fortunes[j].Message } -var ( - // Database - worldStatement *sql.Stmt - fortuneStatement *sql.Stmt - updateStatement *sql.Stmt -) - func parseQueries(c context.Context, ctx *app.RequestContext) int { - n, err := strconv.Atoi(ctx.Query("queries")) - if err != nil { - n = 1 - } else if n < 1 { + n := GetUintOrZeroFromArgs(ctx.QueryArgs(), "queries") + if n < 1 { n = 1 } else if n > 500 { n = 500 @@ -66,122 +72,208 @@ func parseQueries(c context.Context, ctx *app.RequestContext) int { } // / Test 1: JSON serialization -func json(c context.Context, ctx *app.RequestContext) { - ctx.JSON(200, utils.H{"message": "Hello, World!"}) +func jsonhandler(c context.Context, ctx *app.RequestContext) { + m := AcquireJSON() + m.Message = helloworld + ctx.JSON(200, &m) + ReleaseJSON(m) } // / Test 2: Single database query -func db(c context.Context, ctx *app.RequestContext) { - var world World - err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber) - if err != nil { - ctx.AbortWithError(500, err) - return - } +func dbHandler(c context.Context, ctx *app.RequestContext) { + world := AcquireWorld() + db.QueryRow(context.Background(), worldSelect, RandomWorld()).Scan(&world.Id, &world.RandomNumber) ctx.JSON(200, &world) + ReleaseWorld(world) } // / Test 3: Multiple database queries func dbs(c context.Context, ctx *app.RequestContext) { - numQueries := parseQueries(c, ctx) - - worlds := make([]World, numQueries) - for i := 0; i < numQueries; i++ { - err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&worlds[i].Id, &worlds[i].RandomNumber) - if err != nil { - ctx.AbortWithError(500, err) - return - } + n := parseQueries(c, ctx) + worlds := AcquireWorlds()[:n] + for i := 0; i < n; i++ { + w := &worlds[i] + db.QueryRow(context.Background(), worldSelect, RandomWorld()).Scan(&w.Id, &w.RandomNumber) } ctx.JSON(200, &worlds) + ReleaseWorlds(worlds) } // / Test 4: Fortunes func fortunes(c context.Context, ctx *app.RequestContext) { - rows, err := fortuneStatement.Query() - if err != nil { - ctx.AbortWithError(500, err) - return - } - - fortunes := make(Fortunes, 0, 16) + rows, _ := db.Query(context.Background(), fortuneSelect) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} - if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil { - ctx.AbortWithError(500, err) - return - } + _ = rows.Scan(&fortune.Id, &fortune.Message) fortunes = append(fortunes, &fortune) } fortunes = append(fortunes, &Fortune{Message: "Additional fortune added at request time."}) - - sort.Sort(ByMessage{fortunes}) + sort.Slice(fortunes, func(i, j int) bool { + return fortunes[i].Message < fortunes[j].Message + }) ctx.HTML(200, "fortune.html", fortunes) } // / Test 5: Database updates func update(c context.Context, ctx *app.RequestContext) { - numQueries := parseQueries(c, ctx) - world := make([]World, numQueries) - for i := 0; i < numQueries; i++ { - if err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world[i].Id, &world[i].RandomNumber); err != nil { - ctx.AbortWithError(500, err) - return - } - world[i].RandomNumber = uint16(rand.Intn(worldRowCount) + 1) - if _, err := updateStatement.Exec(world[i].RandomNumber, world[i].Id); err != nil { - ctx.AbortWithError(500, err) - return - } + n := parseQueries(c, ctx) + worlds := AcquireWorlds()[:n] + for i := 0; i < n; i++ { + w := &worlds[i] + db.QueryRow(context.Background(), worldSelect, RandomWorld()).Scan(&w.Id, &w.RandomNumber) + w.RandomNumber = int32(RandomWorld()) + } + + // sorting is required for insert deadlock prevention. + sort.Slice(worlds, func(i, j int) bool { + return worlds[i].Id < worlds[j].Id + }) + batch := pgx.Batch{} + for _, w := range worlds { + batch.Queue(worldUpdate, w.RandomNumber, w.Id) } - ctx.JSON(200, world) + db.SendBatch(context.Background(), &batch).Close() + ctx.JSON(200, &worlds) + ReleaseWorlds(worlds) } // / Test 6: plaintext func plaintext(c context.Context, ctx *app.RequestContext) { - ctx.String(200, "Hello, World!") + ctx.SetStatusCode(consts.StatusOK) + ctx.Response.SetBodyString(helloworld) } func main() { h := server.New(config.Option{F: func(o *config.Options) { o.Addr = ":8080" - }, - }) - serverHeader := []string{"Hertz"} + o.DisableHeaderNamesNormalizing = true + }}) + render.ResetJSONMarshal(json.Marshal) h.Use(func(c context.Context, ctx *app.RequestContext) { - ctx.Header("Server", serverHeader[0]) + switch b2s(ctx.Path()) { + case plaintextpath: + plaintext(c, ctx) + case jsonpath: + jsonhandler(c, ctx) + case dbpath: + dbHandler(c, ctx) + case dbspath: + dbs(c, ctx) + case updatepath: + update(c, ctx) + case fortunespath: + fortunes(c, ctx) + } }) h.LoadHTMLGlob("/templates/fortune.html") - h.GET("/json", json) - h.GET("/db", db) - h.GET("/dbs", dbs) - h.GET("/fortunes", fortunes) - h.GET("/update", update) - h.GET("/plaintext", plaintext) h.Spin() } func init() { - runtime.GOMAXPROCS(runtime.NumCPU()) + maxConn := runtime.NumCPU() * 4 - dsn := "benchmarkdbuser:benchmarkdbpass@tcp(%s:3306)/hello_world" - dbhost := "tfb-database" - - db, err := sql.Open("mysql", fmt.Sprintf(dsn, dbhost)) - if err != nil { - log.Fatalf("Error opening database: %v", err) - } - db.SetMaxIdleConns(maxConnectionCount) - worldStatement, err = db.Prepare(worldSelect) + var err error + db, err = pgxpool.New(context.Background(), + fmt.Sprintf( + "host=%s port=%d user=%s password=%s dbname=%s pool_max_conns=%d", + "tfb-database", 5432, + "benchmarkdbuser", + "benchmarkdbpass", + "hello_world", + maxConn, + )) if err != nil { - log.Fatal(err) + panic(err) } - fortuneStatement, err = db.Prepare(fortuneSelect) - if err != nil { - log.Fatal(err) +} + +type Message struct { + Message string `json:"message"` +} + +// JSONpool ... +var JSONpool = sync.Pool{ + New: func() interface{} { + return new(Message) + }, +} + +// AcquireJSON ... +func AcquireJSON() *Message { + return JSONpool.Get().(*Message) +} + +// ReleaseJSON ... +func ReleaseJSON(json *Message) { + json.Message = "" + JSONpool.Put(json) +} + +// WorldPool ... +var WorldPool = sync.Pool{ + New: func() interface{} { + return new(World) + }, +} + +// AcquireWorld ... +func AcquireWorld() *World { + return WorldPool.Get().(*World) +} + +// ReleaseWorld ... +func ReleaseWorld(w *World) { + w.Id = 0 + w.RandomNumber = 0 + WorldPool.Put(w) +} + +// WorldsPool ... +var WorldsPool = sync.Pool{ + New: func() interface{} { + return make(Worlds, 0, 500) + }, +} + +// AcquireWorlds ... +func AcquireWorlds() Worlds { + return WorldsPool.Get().(Worlds) +} + +// ReleaseWorlds ...ReleaseWorlds +func ReleaseWorlds(w Worlds) { + w = w[:0] + WorldsPool.Put(w) +} + +func b2s(b []byte) string { + return unsafe.String(unsafe.SliceData(b), len(b)) +} + +// RandomWorld : +func RandomWorld() int { + return rand.Intn(worldRowCount) + 1 +} + +func GetUintOrZeroFromArgs(a *protocol.Args, key string) int { + b := a.Peek(key) + n := len(b) + if n == 0 { + return 0 } - updateStatement, err = db.Prepare(worldUpdate) - if err != nil { - log.Fatal(err) + v := 0 + for i := 0; i < n; i++ { + c := b[i] + k := c - '0' + if k > 9 { + return 0 + } + vNew := 10*v + int(k) + if vNew < v { + return 0 + } + v = vNew } + return v } diff --git a/frameworks/Go/hertz/hertz-gorm.dockerfile b/frameworks/Go/hertz/hertz-gorm.dockerfile index e083097c782..c12fc259573 100644 --- a/frameworks/Go/hertz/hertz-gorm.dockerfile +++ b/frameworks/Go/hertz/hertz-gorm.dockerfile @@ -1,12 +1,12 @@ -FROM golang:1.18 +FROM golang:1.20 ENV GO111MODULE=on WORKDIR /src/ ADD ./hertz-gorm /src/ -RUN go mod tidy -#- original submission -RUN go build -o app -#RUN go build -tags=jsoniter -o app - tryed this but slower on my pc +RUN go mod download +RUN GOAMD64=v3 go build -o app + +EXPOSE 8080 ENTRYPOINT ["/src/app"] diff --git a/frameworks/Go/hertz/hertz-gorm/go.mod b/frameworks/Go/hertz/hertz-gorm/go.mod index 79f1c410edb..f284bfed3b6 100644 --- a/frameworks/Go/hertz/hertz-gorm/go.mod +++ b/frameworks/Go/hertz/hertz-gorm/go.mod @@ -1,19 +1,20 @@ -module gin-gorm/main +module hertz-gorm/main -go 1.18 +go 1.19 require ( - github.com/cloudwego/hertz v0.4.0 + github.com/cloudwego/hertz v0.7.0 + github.com/goccy/go-json v0.10.2 gorm.io/driver/postgres v1.4.5 - gorm.io/gorm v1.24.1-0.20221019064659-5dd2bb482755 + gorm.io/gorm v1.25.4 ) require ( github.com/bytedance/go-tagexpr/v2 v2.9.2 // indirect github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 // indirect - github.com/bytedance/sonic v1.5.0 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect - github.com/cloudwego/netpoll v0.2.6 // indirect + github.com/bytedance/sonic v1.8.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/cloudwego/netpoll v0.5.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/golang/protobuf v1.5.0 // indirect github.com/henrylee2cn/ameda v1.4.10 // indirect @@ -27,11 +28,10 @@ require ( github.com/jackc/pgtype v1.12.0 // indirect github.com/jackc/pgx/v4 v4.17.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.4 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/nyaruka/phonenumbers v1.0.55 // indirect - github.com/stretchr/testify v1.8.0 // indirect - github.com/tidwall/gjson v1.13.0 // indirect + github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect @@ -40,5 +40,4 @@ require ( golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/frameworks/Go/hertz/hertz-gorm/go.sum b/frameworks/Go/hertz/hertz-gorm/go.sum new file mode 100644 index 00000000000..c84b073dce6 --- /dev/null +++ b/frameworks/Go/hertz/hertz-gorm/go.sum @@ -0,0 +1,262 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/bytedance/go-tagexpr/v2 v2.9.2 h1:QySJaAIQgOEDQBLS3x9BxOWrnhqu5sQ+f6HaZIxD39I= +github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 h1:PtwsQyQJGxf8iaPptPNaduEIu9BnrNms+pcRdHAxZaM= +github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q= +github.com/bytedance/mockey v1.2.1 h1:g84ngI88hz1DR4wZTL3yOuqlEcq67MretBfQUdXwrmw= +github.com/bytedance/mockey v1.2.1/go.mod h1:+Jm/fzWZAuhEDrPXVjDf/jLM2BlLXJkwk94zf2JZ3X4= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.1 h1:NqAHCaGaTzro0xMmnTCLUyRlbEP6r8MCA1cJUrH3Pu4= +github.com/bytedance/sonic v1.8.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/cloudwego/hertz v0.7.0 h1:9LFXPqHkGBNH/k/Y1h3udEloS5LVPNOUWekDfH0bQNM= +github.com/cloudwego/hertz v0.7.0/go.mod h1:WliNtVbwihWHHgAaIQEbVXl0O3aWj0ks1eoPrcEAnjs= +github.com/cloudwego/netpoll v0.5.0 h1:oRrOp58cPCvK2QbMozZNDESvrxQaEHW2dCimmwH1lcU= +github.com/cloudwego/netpoll v0.5.0/go.mod h1:xVefXptcyheopwNDZjDPcfU6kIjZXZ4nY550k1yH9eQ= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/henrylee2cn/ameda v1.4.8/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/ameda v1.4.10 h1:JdvI2Ekq7tapdPsuhrc4CaFiqw6QXFvZIULWJgQyCAk= +github.com/henrylee2cn/ameda v1.4.10/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 h1:yE9ULgp02BhYIrO6sdV/FPe0xQM6fNHkVQW2IAymfM0= +github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8/go.mod h1:Nhe/DM3671a5udlv2AdV2ni/MZzgfv2qrPL5nIi3EGQ= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= +github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y= +github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= +github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= +github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg= +github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc= +gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg= +gorm.io/gorm v1.24.1-0.20221019064659-5dd2bb482755/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= +gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/frameworks/Go/hertz/hertz-gorm/main.go b/frameworks/Go/hertz/hertz-gorm/main.go index 5af39ad66b4..a4283e3b99f 100644 --- a/frameworks/Go/hertz/hertz-gorm/main.go +++ b/frameworks/Go/hertz/hertz-gorm/main.go @@ -2,15 +2,26 @@ package main import ( "context" - "fmt" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" + "github.com/cloudwego/hertz/pkg/app/server/render" "github.com/cloudwego/hertz/pkg/common/config" - "github.com/cloudwego/hertz/pkg/common/utils" - postgres "gorm.io/driver/postgres" + "github.com/cloudwego/hertz/pkg/protocol" + "github.com/goccy/go-json" + "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "math/rand" + "sync" + "unsafe" +) + +const ( + helloworld = "Hello, World!" +) + +var ( + db *gorm.DB ) // World represents an entry int the World table @@ -25,7 +36,7 @@ func (World) TableName() string { } // implements the basic logic behind the query tests -func getWorld(db *gorm.DB) World { +func getWorld(db *gorm.DB) *World { // we could actually precompute a list of random // numbers and slice them but this makes no sense // as I expect that this 'random' is just a placeholder @@ -35,11 +46,11 @@ func getWorld(db *gorm.DB) World { var world World db.Take(&world, randomId) - return world + return &world } // implements the logic behind the updates tests -func processWorld(tx *gorm.DB) (World, error) { +func processWorld(tx *gorm.DB) *World { // we could actually precompute a list of random // numbers and slice them but this makes no sense // as I expect that this 'random' is just a placeholder @@ -51,110 +62,179 @@ func processWorld(tx *gorm.DB) (World, error) { tx.Take(&world, randomId) world.RandomNumber = randomId2 - err := tx.Save(&world).Error + _ = tx.Save(&world) + + return &world +} + +func jsonhandler(c context.Context, ctx *app.RequestContext) { + m := AcquireJSON() + m.Message = helloworld + ctx.JSON(200, &m) + ReleaseJSON(m) +} - return world, err +func plaintext(c context.Context, ctx *app.RequestContext) { + ctx.SetStatusCode(200) + ctx.SetBodyString("Hello, World!") } +func dbHandler(c context.Context, ctx *app.RequestContext) { + world := AcquireWorld() + world = getWorld(db) + ctx.JSON(200, &world) + ReleaseWorld(world) +} + +func parseQueries(c context.Context, ctx *app.RequestContext) int { + n := getUintOrZeroFromArgs(ctx.QueryArgs(), "queries") + if n < 1 { + n = 1 + } else if n > 500 { + n = 500 + } + return n +} + +func queries(c context.Context, ctx *app.RequestContext) { + n := parseQueries(c, ctx) + worlds := AcquireWorlds()[:n] + for i := 0; i < n; i++ { + world := getWorld(db) + worlds[i] = *world + } + ctx.JSON(200, &worlds) + ReleaseWorlds(worlds) +} + +func updates(c context.Context, ctx *app.RequestContext) { + n := parseQueries(c, ctx) + worlds := AcquireWorlds()[:n] + for i := 0; i < n; i++ { + world := processWorld(db) + worlds[i] = *world + } + + ctx.JSON(200, &worlds) + ReleaseWorlds(worlds) +} func main() { /* SETUP DB AND WEB SERVER */ - dsn := "host=tfb-database user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world port=5432 sslmode=disable" - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ + db, _ = gorm.Open(postgres.Open(dsn), &gorm.Config{ PrepareStmt: true, // use prep statements Logger: logger.Default.LogMode(logger.Silent), // new, not inserted in original submission 2x on query }) - if err != nil { - panic("failed to connect database") - } - - sqlDB, err := db.DB() - if err != nil { - panic("failed to get underlying db conn pooling struct") - } + sqlDB, _ := db.DB() - // SetMaxIdleConns sets the maximum number of connections in the idle connection pool. sqlDB.SetMaxIdleConns(500) h := server.New(config.Option{F: func(o *config.Options) { o.Addr = ":8080" - }}) // use default middleware - - // setup middleware to add server header - // this slows things a little, but it is the best design decision - serverHeader := []string{"Hertz-gorm"} + o.DisableHeaderNamesNormalizing = true + }}) + render.ResetJSONMarshal(json.Marshal) h.Use(func(c context.Context, ctx *app.RequestContext) { - ctx.Header("Server", serverHeader[0]) + switch b2S(ctx.Path()) { + case "/json": + jsonhandler(c, ctx) + case "/plaintext": + plaintext(c, ctx) + case "/db": + dbHandler(c, ctx) + case "/queries": + queries(c, ctx) + case "/updates": + updates(c, ctx) + } }) + h.Spin() +} - /* START TESTS */ - // JSON TEST - h.GET("/json", func(c context.Context, ctx *app.RequestContext) { - // ctx.Header("Server", "example") - original submission now using middleware - ctx.JSON(200, utils.H{"message": "Hello, World!"}) - }) - // PLAINTEXT TEST - h.GET("/plaintext", func(c context.Context, ctx *app.RequestContext) { - // ctx.Header("Server", "example") - original submission now using middleware - ctx.String(200, "Hello, World!") - }) - // SINGLE QUERY - h.GET("/db", func(c context.Context, ctx *app.RequestContext) { - world := getWorld(db) - // ctx.Header("Server", "example") - original submission now using middleware - ctx.JSON(200, world) - }) +func b2S(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} - type NumOf struct { - Queries int `form:"queries" query:"queries"` - } - // MULTIPLE QUERIES - h.GET("/queries", func(c context.Context, ctx *app.RequestContext) { - var numOf NumOf - if ctx.Bind(&numOf) != nil { // manage missing query num - numOf.Queries = 1 - } else if numOf.Queries < 1 { // set at least 1 - numOf.Queries = 1 - } else if numOf.Queries > 500 { // set no more than 500 - numOf.Queries = 500 - } +type Message struct { + Message string `json:"message"` +} - worlds := make([]World, numOf.Queries) - for i := 0; i < numOf.Queries; i++ { - worlds[i] = getWorld(db) - } - ctx.JSON(200, &worlds) - }) - // MULTIPLE UPDATES - h.GET("/updates", func(c context.Context, ctx *app.RequestContext) { - var numOf NumOf - - if ctx.Bind(&numOf) != nil { // manage missing query num - numOf.Queries = 1 - } else if numOf.Queries < 1 { // set at least 1 - numOf.Queries = 1 - } else if numOf.Queries > 500 { // set no more than 500 - numOf.Queries = 500 - } +type Worlds []World - worlds := make([]World, numOf.Queries, numOf.Queries) // prealloc - var err error = nil +// JSONpool ... +var JSONpool = sync.Pool{ + New: func() interface{} { + return new(Message) + }, +} - for i := 0; i < numOf.Queries; i++ { - worlds[i], err = processWorld(db) +// AcquireJSON ... +func AcquireJSON() *Message { + return JSONpool.Get().(*Message) +} - if err != nil { - fmt.Println(err) - ctx.JSON(500, utils.H{"error": err}) - break - } - } +// ReleaseJSON ... +func ReleaseJSON(json *Message) { + json.Message = "" + JSONpool.Put(json) +} - ctx.JSON(200, worlds) - }) +// WorldPool ... +var WorldPool = sync.Pool{ + New: func() interface{} { + return new(World) + }, +} - /* START SERVICE */ +// AcquireWorld ... +func AcquireWorld() *World { + return WorldPool.Get().(*World) +} + +// ReleaseWorld ... +func ReleaseWorld(w *World) { + w.ID = 0 + w.RandomNumber = 0 + WorldPool.Put(w) +} + +// WorldsPool ... +var WorldsPool = sync.Pool{ + New: func() interface{} { + return make(Worlds, 0, 500) + }, +} + +// AcquireWorlds ... +func AcquireWorlds() Worlds { + return WorldsPool.Get().(Worlds) +} - h.Spin() // listen and serve on 0.0.0.0:8080 -} \ No newline at end of file +// ReleaseWorlds ...ReleaseWorlds +func ReleaseWorlds(w Worlds) { + w = w[:0] + WorldsPool.Put(w) +} + +func getUintOrZeroFromArgs(a *protocol.Args, key string) int { + b := a.Peek(key) + n := len(b) + if n == 0 { + return 0 + } + v := 0 + for i := 0; i < n; i++ { + c := b[i] + k := c - '0' + if k > 9 { + return 0 + } + vNew := 10*v + int(k) + if vNew < v { + return 0 + } + v = vNew + } + return v +} diff --git a/frameworks/Go/hertz/hertz.dockerfile b/frameworks/Go/hertz/hertz.dockerfile index 0d78b270324..60252e31ffd 100644 --- a/frameworks/Go/hertz/hertz.dockerfile +++ b/frameworks/Go/hertz/hertz.dockerfile @@ -1,15 +1,15 @@ -FROM golang:1.18 +FROM docker.io/golang:1.20 + +WORKDIR /hertz ENV GO111MODULE=on ADD ./ /hertz COPY ./templates /templates -WORKDIR /hertz - -RUN go mod tidy -RUN go build -o hello hello.go +RUN go mod download +RUN GOAMD64=v3 go build -ldflags="-s -w" -o app . EXPOSE 8080 -CMD ./hello +CMD ./app diff --git a/frameworks/Go/kami/src/kami/server.go b/frameworks/Go/kami/src/kami/server.go index 11d249f8dcb..26b9db9c486 100644 --- a/frameworks/Go/kami/src/kami/server.go +++ b/frameworks/Go/kami/src/kami/server.go @@ -129,7 +129,7 @@ func fortuneHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) log.Fatalf("Error preparing statement: %v", err) } - fortunes := make(Fortunes, 0, 16) + fortunes := make(Fortunes, 0) for rows.Next() { //Fetch rows fortune := Fortune{} if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil { diff --git a/frameworks/Go/revel/src/benchmark/app/controllers/app.go b/frameworks/Go/revel/src/benchmark/app/controllers/app.go index f93011aa006..2a993e5fec2 100644 --- a/frameworks/Go/revel/src/benchmark/app/controllers/app.go +++ b/frameworks/Go/revel/src/benchmark/app/controllers/app.go @@ -7,7 +7,6 @@ import ( dbm "benchmark/app/db" - "github.com/revel/modules/db/app" "github.com/revel/revel" ) @@ -84,13 +83,13 @@ func (c App) Plaintext() revel.Result { } func (c App) Db(queries int) revel.Result { - _, foundQuery := c.Params.Values["queries"] - if queries>500 { - queries = 500 - } - if queries == 0 { - queries = 1 - } + _, foundQuery := c.Params.Values["queries"] + if queries > 500 { + queries = 500 + } + if queries == 0 { + queries = 1 + } ww := make([]World, queries) for i := 0; i < queries; i++ { err := worldStatement.QueryRow(rand.Intn(WorldRowCount)+1). @@ -99,19 +98,19 @@ func (c App) Db(queries int) revel.Result { c.Log.Fatalf("Error scanning world row: %v", err) } } - if !foundQuery { - return c.RenderJSON(ww[0]) - } + if !foundQuery { + return c.RenderJSON(ww[0]) + } return c.RenderJSON(ww) } func (c App) Update(queries int) revel.Result { - _, foundQuery := c.Params.Values["queries"] - if queries>500 { - queries = 500 - } else if queries == 0 { - queries = 1 - } + _, foundQuery := c.Params.Values["queries"] + if queries > 500 { + queries = 500 + } else if queries == 0 { + queries = 1 + } ww := make([]World, queries) for i := 0; i < queries; i++ { err := worldStatement.QueryRow(rand.Intn(WorldRowCount)+1). @@ -122,14 +121,14 @@ func (c App) Update(queries int) revel.Result { ww[i].RandomNumber = uint16(rand.Intn(WorldRowCount) + 1) updateStatement.Exec(ww[i].RandomNumber, ww[i].Id) } - if !foundQuery { - return c.RenderJSON(ww[0]) - } - return c.RenderJSON(ww) + if !foundQuery { + return c.RenderJSON(ww[0]) + } + return c.RenderJSON(ww) } func (c App) Fortune() revel.Result { - fortunes := make([]*Fortune, 0, 16) + fortunes := make([]*Fortune, 0) rows, err := fortuneStatement.Query() if err != nil { diff --git a/frameworks/Java/micronaut/gradle.properties b/frameworks/Java/micronaut/gradle.properties index 6a89a816645..b292646568c 100644 --- a/frameworks/Java/micronaut/gradle.properties +++ b/frameworks/Java/micronaut/gradle.properties @@ -1 +1 @@ -micronautVersion = 4.1.4 +micronautVersion = 4.1.6 diff --git a/frameworks/JavaScript/nodejs/app.js b/frameworks/JavaScript/nodejs/app.js index 386642c479c..95c97a34291 100755 --- a/frameworks/JavaScript/nodejs/app.js +++ b/frameworks/JavaScript/nodejs/app.js @@ -1,7 +1,7 @@ const cluster = require('cluster'); const numCPUs = require('os').cpus().length; -process.env.NODE_HANDLER = 'mysql-raw'; +process.env.NODE_HANDLER = 'postgres'; if (process.env.TFB_TEST_NAME === 'nodejs-mongodb') { process.env.NODE_HANDLER = 'mongoose'; @@ -9,8 +9,12 @@ if (process.env.TFB_TEST_NAME === 'nodejs-mongodb') { process.env.NODE_HANDLER = 'mongodb-raw'; } else if (process.env.TFB_TEST_NAME === 'nodejs-mysql') { process.env.NODE_HANDLER = 'sequelize'; +} else if (process.env.TFB_TEST_NAME === 'nodejs-mysql-raw') { + process.env.NODE_HANDLER = 'mysql-raw'; } else if (process.env.TFB_TEST_NAME === 'nodejs-postgres') { process.env.NODE_HANDLER = 'sequelize-postgres'; +}else if (process.env.TFB_TEST_NAME === 'nodejs-postgresjs-raw') { + process.env.NODE_HANDLER = 'postgres'; } if (cluster.isPrimary) { diff --git a/frameworks/JavaScript/nodejs/benchmark_config.json b/frameworks/JavaScript/nodejs/benchmark_config.json index fc406969359..dbabf139333 100644 --- a/frameworks/JavaScript/nodejs/benchmark_config.json +++ b/frameworks/JavaScript/nodejs/benchmark_config.json @@ -4,61 +4,75 @@ "default": { "json_url": "/json", "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "nodejs", + "language": "JavaScript", + "flavor": "NodeJS", + "orm": "Raw", + "platform": "nodejs", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "nodejs", + "notes": "", + "versus": "nodejs" + }, + "mongodb": { + "dockerfile": "nodejs.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", - "cached_query_url": "/cached?queries=", "update_url": "/updates?queries=", - "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "MySQL", + "database": "MongoDB", "framework": "nodejs", "language": "JavaScript", "flavor": "NodeJS", - "orm": "Raw", + "orm": "Full", "platform": "nodejs", "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "nodejs", + "display_name": "nodejs-mongodb", "notes": "", "versus": "nodejs" }, - "chakra": { + "mongodb-raw": { "dockerfile": "nodejs.dockerfile", - "json_url": "/json", - "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", - "cached_query_url": "/cached?queries=", "update_url": "/updates?queries=", "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "MySQL", - "framework": "None", + "database": "MongoDB", + "framework": "nodejs", "language": "JavaScript", - "flavor": "node-chakracore", + "flavor": "NodeJS", "orm": "Raw", "platform": "nodejs", "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "node-chakracore", + "display_name": "nodejs-mongodb-raw", "notes": "", "versus": "nodejs" }, - "mongodb": { + "mysql": { "dockerfile": "nodejs.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "MongoDB", + "database": "MySQL", "framework": "nodejs", "language": "JavaScript", "flavor": "NodeJS", @@ -67,20 +81,21 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "nodejs", + "display_name": "nodejs-mysql", "notes": "", "versus": "nodejs" }, - "mongodb-raw": { + "mysql-raw": { "dockerfile": "nodejs.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", "fortune_url": "/fortunes", + "cached_query_url": "/cached?queries=", "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "MongoDB", + "database": "MySQL", "framework": "nodejs", "language": "JavaScript", "flavor": "NodeJS", @@ -89,11 +104,11 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "nodejs", + "display_name": "nodejs-mysql-raw", "notes": "", "versus": "nodejs" }, - "mysql": { + "postgresjs-raw": { "dockerfile": "nodejs.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", @@ -102,16 +117,16 @@ "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "MySQL", + "database": "Postgres", "framework": "nodejs", "language": "JavaScript", "flavor": "NodeJS", - "orm": "Full", + "orm": "Raw", "platform": "nodejs", "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "nodejs", + "display_name": "nodejs-postgresjs-raw", "notes": "", "versus": "nodejs" }, @@ -133,7 +148,7 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "nodejs", + "display_name": "nodejs-postgres-sequel", "notes": "", "versus": "nodejs" } diff --git a/frameworks/JavaScript/nodejs/handlers/postgres.js b/frameworks/JavaScript/nodejs/handlers/postgres.js new file mode 100644 index 00000000000..c7411c64fad --- /dev/null +++ b/frameworks/JavaScript/nodejs/handlers/postgres.js @@ -0,0 +1,109 @@ +const postgres = require("postgres"); +const NodeCache = require("node-cache"); +const h = require("../helper"); + +const sql = postgres({ + host: "tfb-database", + user: "benchmarkdbuser", + password: "benchmarkdbpass", + database: "hello_world", + max: 1, +}); + +const dbfortunes = async () => await sql`SELECT id, message FROM fortune`; + +const dbfind = async (id) => + await sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then( + (arr) => arr[0] + ); + +const dbbulkUpdate = async (worlds) => + await sql`UPDATE world SET randomNumber = (update_data.randomNumber)::int + FROM (VALUES ${sql( + worlds + .map((world) => [world.id, world.randomNumber]) + .sort((a, b) => (a[0] < b[0] ? -1 : 1)) + )}) AS update_data (id, randomNumber) + WHERE world.id = (update_data.id)::int`; + +const dbgetAllWorlds = async () => sql`SELECT id, randomNumber FROM world`; + +const extra = h.additionalFortune(); + +const myCache = new NodeCache({ stdTTL: 0, checkperiod: 0 }); + +let isCachePopulated = false; + +const populateCache = (callback) => { + if (isCachePopulated) return callback(); + + dbgetAllWorlds().then((worlds) => { + for (let i = 0; i < worlds.length; i++) { + myCache.set(worlds[i].id, worlds[i]); + } + isCachePopulated = true; + callback(); + }); +}; + +module.exports = { + SingleQuery: async (req, res) => { + const row = await dbfind(h.generateRandomNumber()); + h.writeResponse(res, h.worldObjectSerializer(row)); + }, + + MultipleQueries: async (queries, req, res) => { + const databaseJobs = new Array(queries); + for (let i = 0; i < queries; i++) { + databaseJobs[i] = dbfind(h.generateRandomNumber()); + } + const worldObjects = await Promise.all(databaseJobs); + + h.writeResponse(res, JSON.stringify(worldObjects)); + }, + + Fortunes: async (req, res) => { + const rows = [extra, ...(await dbfortunes())]; + h.sortByMessage(rows); + const n = rows.length; + let html = "", i = 0; + for (; i < n; i++) { + html += `${rows[i].id}${h.escapeHtmlFromText(rows[i].message)}`; + } + + h.writeResponse( + res, + `Fortunes${html}
idmessage
`, + h.headerTypes["html"] + ); + }, + + Updates: async (queries, req, res) => { + const databaseJobs = new Array(queries); + + for (let i = 0; i < queries; i++) { + databaseJobs[i] = dbfind(h.generateRandomNumber()); + } + + const worldObjects = await Promise.all(databaseJobs); + + for (let i = 0; i < queries; i++) { + worldObjects[i].randomNumber = h.generateRandomNumber(); + } + + await dbbulkUpdate(worldObjects); + + h.writeResponse(res, JSON.stringify(worldObjects)); + }, + CachedQueries: (queries, req, res) => { + populateCache(() => { + const worlds = new Array(queries); + + for (let i = 0; i < queries; i++) { + worlds[i] = myCache.get(h.generateRandomNumber()); + } + + h.writeResponse(res, JSON.stringify(worlds)); + }); + }, +}; diff --git a/frameworks/JavaScript/nodejs/helper.js b/frameworks/JavaScript/nodejs/helper.js index 4c6d6161bf0..6f8e9793c77 100644 --- a/frameworks/JavaScript/nodejs/helper.js +++ b/frameworks/JavaScript/nodejs/helper.js @@ -1,4 +1,5 @@ const Handlebars = require('handlebars'); +const { sjs, attr } = require("slow-json-stringify"); const GREETING = "Hello, World!"; @@ -8,33 +9,79 @@ const headerTypes = { html: 'text/html; charset=UTF-8' }; -const self = module.exports = { +function sortByMessage(arr) { + const n = arr.length; + for (let i = 1; i < n; i++) { + const c = arr[i]; + let j = i - 1; + while (j > -1 && c.message < arr[j].message) { + arr[j + 1] = arr[j]; + j--; + } + arr[j + 1] = c; + } + return arr; +} + +function generateRandomNumber(){ + return Math.ceil(Math.random() * 10000); +} + +const jsonSerializer = sjs({ message: attr("string") }); +const worldObjectSerializer = sjs({ id: attr("number"), randomnumber: attr("number")}); +const escapeHTMLRules = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' } + +const unsafeHTMLMatcher = /[&<>"'\/]/g + +function escapeHtmlFromText(text) { + if (unsafeHTMLMatcher.test(text) === false) return text; + return text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; }); +} + +function writeResponse(res, text, type = headerTypes["json"]) { + res.writeHead(200, { + "content-type": type, + server: "Node", + }); + res.end(text); +} + +const self = (module.exports = { + sortByMessage, + generateRandomNumber, + jsonSerializer, + worldObjectSerializer, + escapeHtmlFromText, + writeResponse, + headerTypes, additionalFortune: () => ({ id: 0, - message: 'Additional fortune added at request time.' + message: "Additional fortune added at request time.", }), - fortunesTemplate: Handlebars.compile([ - "", - "", - "Fortunes", - "", - "", + fortunesTemplate: Handlebars.compile( + [ + "", + "", + "Fortunes", + "", + "
", "", - "", - "", + "", + "", "", "{{#fortunes}}", "", - "", - "", + "", + "", "", "{{/fortunes}}", - "
idmessageidmessage
{{id}}{{message}}{{id}}{{message}}
", - "", - "" - ].join('')), + "", + "", + "", + ].join("") + ), randomTfbNumber: () => Math.floor(Math.random() * 10000) + 1, @@ -49,27 +96,23 @@ const self = module.exports = { addTfbHeaders: (res, headerType) => { res.setHeader('Server', 'Node'); res.setHeader('Content-Type', headerTypes[headerType]); -}, + }, responses: { - jsonSerialization: (req, res) => { - const HELLO_OBJ = { message: GREETING }; - self.addTfbHeaders(res, 'json'); - res.end(JSON.stringify(HELLO_OBJ)); + writeResponse(res, jsonSerializer({ message: GREETING })); }, plaintext: (req, res) => { - self.addTfbHeaders(res, 'plain'); - res.end(GREETING); + writeResponse(res, GREETING, headerTypes['plain']); }, routeNotImplemented: (req, res) => { - res.writeHead(501, {'Content-Type': 'text/plain; charset=UTF-8'}); - const reason = { reason: "`" + req.url + "` is not an implemented route" }; + res.writeHead(501, { "Content-Type": "text/plain; charset=UTF-8" }); + const reason = { + reason: "`" + req.url + "` is not an implemented route", + }; res.end(JSON.stringify(reason)); - } - - } - -}; + }, + }, +}); diff --git a/frameworks/JavaScript/nodejs/nodejs.dockerfile b/frameworks/JavaScript/nodejs/nodejs.dockerfile index ed811c100e5..f5b784108d8 100644 --- a/frameworks/JavaScript/nodejs/nodejs.dockerfile +++ b/frameworks/JavaScript/nodejs/nodejs.dockerfile @@ -1,4 +1,4 @@ -FROM node:18.12.1-slim +FROM node:21.1.0-slim ARG TFB_TEST_NAME @@ -6,6 +6,7 @@ COPY ./ ./ RUN npm install +ENV NODE_ENV production ENV TFB_TEST_NAME=$TFB_TEST_NAME EXPOSE 8080 diff --git a/frameworks/JavaScript/nodejs/package.json b/frameworks/JavaScript/nodejs/package.json index 7fd862b83c1..3c7a14550af 100644 --- a/frameworks/JavaScript/nodejs/package.json +++ b/frameworks/JavaScript/nodejs/package.json @@ -12,6 +12,8 @@ "parseurl": "1.3.2", "pg": "8.5.0", "pg-hstore": "2.3.2", + "postgres": "^3.4.3", + "slow-json-stringify": "^2.0.1", "sequelize": "6.29.0", "node-cache": "4.1.1" }, diff --git a/frameworks/Kotlin/hexagon/README.md b/frameworks/Kotlin/hexagon/README.md index 28397711a58..fafc6a6bbc8 100644 --- a/frameworks/Kotlin/hexagon/README.md +++ b/frameworks/Kotlin/hexagon/README.md @@ -15,41 +15,3 @@ To run the full benchmarks locally, on the project root (not this directory) exe ## Infrastructure Software Versions * [Hexagon stable version](http://hexagonkt.com) - -## Test URLs - -### Jetty - -* JSON Encoding Test: http://localhost:9090/json -* Plain Text Test: http://localhost:9090/plaintext -* Data-Store/Database Mapping Test: http://localhost:9090/db?queries=5 -* Fortunes: http://localhost:9090/fortunes -* Database updates: http://localhost:9090/update -* Database queries: http://localhost:9090/query - -### Netty - -* JSON Encoding Test: http://localhost:9090/json -* Plain Text Test: http://localhost:9090/plaintext -* Data-Store/Database Mapping Test: http://localhost:9090/db?queries=5 -* Fortunes: http://localhost:9090/fortunes -* Database updates: http://localhost:9090/update -* Database queries: http://localhost:9090/query - -### Netty Epoll - -* JSON Encoding Test: http://localhost:9090/json -* Plain Text Test: http://localhost:9090/plaintext -* Data-Store/Database Mapping Test: http://localhost:9090/db?queries=5 -* Fortunes: http://localhost:9090/fortunes -* Database updates: http://localhost:9090/update -* Database queries: http://localhost:9090/query - -### Tomcat - -* JSON Encoding Test: http://localhost:8080/json -* Plain Text Test: http://localhost:8080/plaintext -* Data-Store/Database Mapping Test: http://localhost:8080/db?queries=5 -* Fortunes: http://localhost:8080/fortunes -* Database updates: http://localhost:8080/update -* Database queries: http://localhost:8080/query diff --git a/frameworks/Kotlin/hexagon/benchmark_config.json b/frameworks/Kotlin/hexagon/benchmark_config.json index 053d701f5ee..8155e24b68c 100644 --- a/frameworks/Kotlin/hexagon/benchmark_config.json +++ b/frameworks/Kotlin/hexagon/benchmark_config.json @@ -140,7 +140,7 @@ "notes": "http://hexagonkt.com", "versus": "netty" }, - "nima": { + "helidon": { "json_url": "/json", "db_url": "/db", "query_url": "/query?queries=", @@ -159,11 +159,11 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "Hexagon Nima PostgreSQL", + "display_name": "Hexagon Helidon PostgreSQL", "notes": "http://hexagonkt.com", - "versus": "helidon-nima" + "versus": "helidon-helidon" }, - "nima-native": { + "helidon-native": { "json_url": "/json", "db_url": "/db", "query_url": "/query?queries=", @@ -182,11 +182,11 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "Hexagon Nima Native PostgreSQL", + "display_name": "Hexagon Helidon Native PgClient", "notes": "http://hexagonkt.com", - "versus": "helidon-nima" + "versus": "helidon-helidon" }, - "nima-pgclient": { + "helidon-pgclient": { "json_url": "/json", "db_url": "/db", "query_url": "/query?queries=", @@ -205,9 +205,9 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "Hexagon Nima PgClient", + "display_name": "Hexagon Helidon PgClient", "notes": "http://hexagonkt.com", - "versus": "helidon-nima" + "versus": "helidon-helidon" }, "tomcat": { "json_url": "/json", diff --git a/frameworks/Kotlin/hexagon/build.gradle b/frameworks/Kotlin/hexagon/build.gradle index e89a6493bdf..06489534605 100644 --- a/frameworks/Kotlin/hexagon/build.gradle +++ b/frameworks/Kotlin/hexagon/build.gradle @@ -1,7 +1,7 @@ plugins { - id "org.jetbrains.kotlin.jvm" version "1.9.10" apply false - id "org.graalvm.buildtools.native" version "0.9.25" apply false + id "org.jetbrains.kotlin.jvm" version "1.9.20" apply false + id "org.graalvm.buildtools.native" version "0.9.28" apply false } version = "1.0.0" @@ -9,18 +9,17 @@ description = "TFB benchmark" group = "com.hexagonkt" ext { - hexagonVersion = "3.1.0" - jettyVersion = "12.0.0" - nettyVersion = "4.1.97.Final" + hexagonVersion = "3.4.3" + jettyVersion = "12.0.3" + nettyVersion = "4.1.100.Final" - hikariVersion = "5.0.1" + hikariVersion = "5.1.0" postgresqlVersion = "42.6.0" - vertxVersion = "4.4.5" + vertxVersion = "4.4.6" cache2kVersion = "2.6.1.Final" applicationClass = "com.hexagonkt.BenchmarkKt" modules = "java.naming,java.sql,java.management" - options = "--enable-preview" gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/$hexagonVersion/gradle" } @@ -29,3 +28,7 @@ subprojects { apply(from: "$gradleScripts/kotlin.gradle") } + +tasks.wrapper { + gradleVersion = "8.4" +} diff --git a/frameworks/Kotlin/hexagon/config.toml b/frameworks/Kotlin/hexagon/config.toml index d00c779ea55..6f25ab27753 100644 --- a/frameworks/Kotlin/hexagon/config.toml +++ b/frameworks/Kotlin/hexagon/config.toml @@ -109,7 +109,7 @@ platform = "Netty" webserver = "None" versus = "netty" -[nima] +[helidon] urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" @@ -125,9 +125,9 @@ os = "Linux" orm = "Raw" platform = "Helidon" webserver = "None" -versus = "helidon-nima" +versus = "helidon-helidon" -[nima-native] +[helidon-native] urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" @@ -143,9 +143,9 @@ os = "Linux" orm = "Raw" platform = "Helidon" webserver = "None" -versus = "helidon-nima" +versus = "helidon-helidon" -[nima-pgclient] +[helidon-pgclient] urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" @@ -161,7 +161,7 @@ os = "Linux" orm = "Raw" platform = "Helidon" webserver = "None" -versus = "helidon-nima" +versus = "helidon-helidon" [tomcat] urls.plaintext = "/plaintext" diff --git a/frameworks/Kotlin/hexagon/core/build.gradle b/frameworks/Kotlin/hexagon/core/build.gradle index 4cf6f44b80c..18212db6bee 100644 --- a/frameworks/Kotlin/hexagon/core/build.gradle +++ b/frameworks/Kotlin/hexagon/core/build.gradle @@ -1,20 +1,21 @@ plugins { - id("nu.studer.rocker") version("3.0.4") + id("gg.jte.gradle") version("3.1.4") } dependencies { api(project(":model")) api("com.hexagonkt:http_server:$hexagonVersion") - api("com.hexagonkt:templates_rocker:$hexagonVersion") - api("com.hexagonkt:logging_slf4j_jul:$hexagonVersion") + api("com.hexagonkt:templates_jte:$hexagonVersion") api("com.hexagonkt:serialization_jackson_json:$hexagonVersion") api("org.cache2k:cache2k-core:$cache2kVersion") + + jteGenerate("gg.jte:jte-native-resources:3.1.4") } tasks.register("minimizeTemplate") { doLast { - File template = file("$buildDir/resources/main/fortunes.rocker.html") + File template = file("$buildDir/resources/main/fortunes.jte") List lines = template.readLines().collect { it.trim() } template.write(lines.join("")) } @@ -22,11 +23,11 @@ tasks.register("minimizeTemplate") { jar.dependsOn("minimizeTemplate") -rocker { - configurations { - create("main") { - templateDir.set(file("src/main/resources")) - optimize.set(true) - } - } +jte { + sourceDirectory.set(file("src/main/resources").toPath()) + targetDirectory.set(file("build/classes/kotlin/main").toPath()) + + jteExtension("gg.jte.nativeimage.NativeResourcesExtension") + + generate() } diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties index 9f3cd246318..4dac65fae39 100644 --- a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties +++ b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/native-image.properties @@ -1,8 +1,5 @@ Args= \ - -H:IncludeResources=.*\\.(html|class) \ - --enable-preview \ + -march=native \ --static \ --libc=musl \ - --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter \ - --initialize-at-build-time=org.slf4j.jul.JDK14LoggerAdapter$1 \ --initialize-at-build-time=org.slf4j.LoggerFactory diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json b/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json deleted file mode 100644 index 11815306be2..00000000000 --- a/frameworks/Kotlin/hexagon/core/src/main/resources/META-INF/native-image/com.hexagonkt.benchmark/core/reflect-config.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "name": "fortunes", - "allPublicMethods": true, - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "fortunes$Template", - "allPublicMethods": true, - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - }, - { - "name": "fortunes$PlainText", - "allPublicMethods": true, - "allDeclaredFields": true, - "allDeclaredMethods": true, - "allDeclaredConstructors": true - } -] diff --git a/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.rocker.html b/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.jte similarity index 57% rename from frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.rocker.html rename to frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.jte index c9a9d4037e5..82b28ce94c3 100644 --- a/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.rocker.html +++ b/frameworks/Kotlin/hexagon/core/src/main/resources/fortunes.jte @@ -1,6 +1,8 @@ @import java.util.* @import com.hexagonkt.model.Fortune -@args(Map context) + +@param List fortunes + @@ -13,12 +15,12 @@ id message - @for ((fortune) : (Collection)context.get("fortunes")) { + @for(var fortune : fortunes) - @fortune.getId() - @fortune.getMessage() + ${fortune.getId()} + ${fortune.getMessage()} - } + @endfor diff --git a/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties index 50bed7a3fb7..3fa8f862f75 100644 --- a/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/hexagon/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/frameworks/Kotlin/hexagon/gradlew b/frameworks/Kotlin/hexagon/gradlew index 0adc8e1a532..1aa94a42690 100755 --- a/frameworks/Kotlin/hexagon/gradlew +++ b/frameworks/Kotlin/hexagon/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/frameworks/Kotlin/hexagon/hexagon-nima-native.dockerfile b/frameworks/Kotlin/hexagon/hexagon-helidon-native.dockerfile similarity index 50% rename from frameworks/Kotlin/hexagon/hexagon-nima-native.dockerfile rename to frameworks/Kotlin/hexagon/hexagon-helidon-native.dockerfile index 5e10595efaf..54ddbfc48c4 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nima-native.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-helidon-native.dockerfile @@ -1,21 +1,21 @@ # # BUILD # -FROM ghcr.io/graalvm/native-image-community:20-muslib-ol9 as build +FROM ghcr.io/graalvm/native-image-community:21-muslib-ol9 as build USER root WORKDIR /hexagon ADD . . RUN microdnf -y install findutils RUN ./gradlew --quiet classes -RUN ./gradlew --quiet -x test hexagon_nima_postgresql:nativeCompile +RUN ./gradlew --quiet -x test hexagon_helidon_pgclient:nativeCompile # # RUNTIME # FROM scratch -ARG PROJECT=hexagon_nima_postgresql +ARG PROJECT=hexagon_helidon_pgclient COPY --from=build /hexagon/$PROJECT/build/native/nativeCompile/$PROJECT / -ENTRYPOINT [ "/hexagon_nima_postgresql" ] +ENTRYPOINT [ "/hexagon_helidon_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-nima.dockerfile b/frameworks/Kotlin/hexagon/hexagon-helidon-pgclient.dockerfile similarity index 61% rename from frameworks/Kotlin/hexagon/hexagon-nima.dockerfile rename to frameworks/Kotlin/hexagon/hexagon-helidon-pgclient.dockerfile index 7f2acab2d31..0ecb7488d43 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nima.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-helidon-pgclient.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,12 +12,12 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:20-jre-alpine -ARG PROJECT=hexagon_nima_postgresql +FROM docker.io/eclipse-temurin:21-jre-alpine +ARG PROJECT=hexagon_helidon_pgclient ENV POSTGRESQL_DB_HOST tfb-database ENV JDK_JAVA_OPTIONS --enable-preview -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -ENTRYPOINT [ "/opt/hexagon_nima_postgresql/bin/hexagon_nima_postgresql" ] +ENTRYPOINT [ "/opt/hexagon_helidon_pgclient/bin/hexagon_helidon_pgclient" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-nima-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-helidon.dockerfile similarity index 60% rename from frameworks/Kotlin/hexagon/hexagon-nima-pgclient.dockerfile rename to frameworks/Kotlin/hexagon/hexagon-helidon.dockerfile index 6500113e675..5c790a00c72 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nima-pgclient.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-helidon.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,12 +12,12 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:20-jre-alpine -ARG PROJECT=hexagon_nima_pgclient +FROM docker.io/eclipse-temurin:21-jre-alpine +ARG PROJECT=hexagon_helidon_postgresql ENV POSTGRESQL_DB_HOST tfb-database ENV JDK_JAVA_OPTIONS --enable-preview -XX:+AlwaysPreTouch -XX:+UseParallelGC -XX:+UseNUMA COPY --from=build /hexagon/$PROJECT/build/install/$PROJECT /opt/$PROJECT -ENTRYPOINT [ "/opt/hexagon_nima_pgclient/bin/hexagon_nima_pgclient" ] +ENTRYPOINT [ "/opt/hexagon_helidon_postgresql/bin/hexagon_helidon_postgresql" ] diff --git a/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile index 61f63ad0af8..3e9f700ba25 100644 --- a/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-jetty-native.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM ghcr.io/graalvm/native-image-community:17-muslib-ol9 as build +FROM ghcr.io/graalvm/native-image-community:21-muslib-ol9 as build USER root WORKDIR /hexagon diff --git a/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile index 88aaf007449..10f40528c0a 100644 --- a/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-jettyloom-pgclient.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:20-jre-alpine +FROM docker.io/eclipse-temurin:21-jre-alpine ARG PROJECT=hexagon_jetty_pgclient ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile b/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile index 254f4edfe16..ce807d1c2fe 100644 --- a/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-jettyloom.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:20-jre-alpine +FROM docker.io/eclipse-temurin:21-jre-alpine ARG PROJECT=hexagon_jetty_postgresql ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile b/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile index 5b120fb19eb..d07a610bcd8 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-nettyepoll-pgclient.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:21-jre-alpine ARG PROJECT=hexagon_nettyepoll_pgclient ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile b/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile index 9a07262affb..c813f85bf27 100644 --- a/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-nettyepoll.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:21-jre-alpine ARG PROJECT=hexagon_nettyepoll_postgresql ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile b/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile index d6b9a9e504a..c28cb74d5d4 100644 --- a/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon-tomcat.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test war # # RUNTIME # -FROM docker.io/tomcat:10-jre17-temurin-jammy +FROM docker.io/tomcat:10-jre21-temurin-jammy ARG MODULE=/hexagon/hexagon_tomcat_postgresql ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon.dockerfile b/frameworks/Kotlin/hexagon/hexagon.dockerfile index 2a62cbac2ba..7723b0cae2d 100644 --- a/frameworks/Kotlin/hexagon/hexagon.dockerfile +++ b/frameworks/Kotlin/hexagon/hexagon.dockerfile @@ -1,7 +1,7 @@ # # BUILD # -FROM docker.io/gradle:8.3-jdk17-alpine AS build +FROM docker.io/gradle:8.4-jdk21-alpine AS build USER root WORKDIR /hexagon @@ -12,7 +12,7 @@ RUN gradle --quiet -x test installDist # # RUNTIME # -FROM docker.io/eclipse-temurin:17-jre-alpine +FROM docker.io/eclipse-temurin:21-jre-alpine ARG PROJECT=hexagon_jetty_postgresql ENV POSTGRESQL_DB_HOST tfb-database diff --git a/frameworks/Kotlin/hexagon/hexagon_nima_postgresql/build.gradle b/frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/build.gradle similarity index 53% rename from frameworks/Kotlin/hexagon/hexagon_nima_postgresql/build.gradle rename to frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/build.gradle index 2957919e905..5e64c7bde3f 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nima_postgresql/build.gradle +++ b/frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/build.gradle @@ -3,6 +3,6 @@ apply(from: "$gradleScripts/application.gradle") apply(from: "$gradleScripts/native.gradle") dependencies { - api(project(":store_sql")) - api("com.hexagonkt:http_server_nima:$hexagonVersion") + api(project(":store_pgclient")) + api("com.hexagonkt:http_server_helidon:$hexagonVersion") } diff --git a/frameworks/Kotlin/hexagon/hexagon_nima_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/src/main/kotlin/Benchmark.kt similarity index 50% rename from frameworks/Kotlin/hexagon/hexagon_nima_pgclient/src/main/kotlin/Benchmark.kt rename to frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/src/main/kotlin/Benchmark.kt index 9df2914829b..d38d33281f8 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nima_pgclient/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_helidon_pgclient/src/main/kotlin/Benchmark.kt @@ -1,16 +1,17 @@ package com.hexagonkt +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf -import com.hexagonkt.http.server.nima.NimaServerAdapter +import com.hexagonkt.http.server.helidon.HelidonServerAdapter import com.hexagonkt.store.BenchmarkPgClientStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter fun main() { val settings = Settings() val store = BenchmarkPgClientStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") - val engine = NimaServerAdapter() + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") + val engine = HelidonServerAdapter() val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) benchmark.server.start() diff --git a/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/build.gradle b/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/build.gradle new file mode 100644 index 00000000000..1fb3fbffab6 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/build.gradle @@ -0,0 +1,7 @@ + +apply(from: "$gradleScripts/application.gradle") + +dependencies { + api(project(":store_sql")) + api("com.hexagonkt:http_server_helidon:$hexagonVersion") +} diff --git a/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/src/main/kotlin/Benchmark.kt new file mode 100644 index 00000000000..cbfb372cbd5 --- /dev/null +++ b/frameworks/Kotlin/hexagon/hexagon_helidon_postgresql/src/main/kotlin/Benchmark.kt @@ -0,0 +1,18 @@ +package com.hexagonkt + +import com.hexagonkt.core.media.TEXT_HTML +import com.hexagonkt.core.urlOf +import com.hexagonkt.http.server.helidon.HelidonServerAdapter +import com.hexagonkt.store.BenchmarkSqlStore +import com.hexagonkt.templates.jte.JteAdapter + +fun main() { + val settings = Settings() + val store = BenchmarkSqlStore("postgresql") + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") + val engine = HelidonServerAdapter() + + val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) + benchmark.server.start() +} diff --git a/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/src/main/kotlin/Benchmark.kt index 563f89fd60b..c6e8dbcf855 100644 --- a/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_jetty_pgclient/src/main/kotlin/Benchmark.kt @@ -1,16 +1,17 @@ package com.hexagonkt import com.hexagonkt.core.Jvm.systemFlag +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf import com.hexagonkt.http.server.jetty.JettyServletAdapter import com.hexagonkt.store.BenchmarkPgClientStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter fun main() { val settings = Settings() val store = BenchmarkPgClientStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") val engine = JettyServletAdapter( sendDateHeader = settings.sendDateHeader, sendServerVersion = settings.sendServerVersion, diff --git a/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/src/main/kotlin/Benchmark.kt index 8e39a09de63..64585b785b6 100644 --- a/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_jetty_postgresql/src/main/kotlin/Benchmark.kt @@ -1,16 +1,17 @@ package com.hexagonkt import com.hexagonkt.core.Jvm.systemFlag +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf import com.hexagonkt.http.server.jetty.JettyServletAdapter import com.hexagonkt.store.BenchmarkSqlStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter fun main() { val settings = Settings() val store = BenchmarkSqlStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") val engine = JettyServletAdapter( sendDateHeader = settings.sendDateHeader, sendServerVersion = settings.sendServerVersion, diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt index 40bca0a1428..0bbd8038edd 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_pgclient/src/main/kotlin/Benchmark.kt @@ -1,9 +1,10 @@ package com.hexagonkt +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf import com.hexagonkt.http.server.netty.epoll.NettyEpollServerAdapter import com.hexagonkt.store.BenchmarkPgClientStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter import io.netty.util.ResourceLeakDetector import io.netty.util.ResourceLeakDetector.Level.DISABLED @@ -15,9 +16,14 @@ fun main() { val settings = Settings() val store = BenchmarkPgClientStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") - val engine = NettyEpollServerAdapter() + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") + val engine = NettyEpollServerAdapter( + keepAliveHandler = false, + httpAggregatorHandler = false, + chunkedHandler = false, + enableWebsockets = false, + ) val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) benchmark.server.start() diff --git a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt index 6e5463e880c..77fa370b915 100644 --- a/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt +++ b/frameworks/Kotlin/hexagon/hexagon_nettyepoll_postgresql/src/main/kotlin/Benchmark.kt @@ -1,9 +1,10 @@ package com.hexagonkt +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf import com.hexagonkt.http.server.netty.epoll.NettyEpollServerAdapter import com.hexagonkt.store.BenchmarkSqlStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter import io.netty.util.ResourceLeakDetector import io.netty.util.ResourceLeakDetector.Level.DISABLED @@ -15,9 +16,14 @@ fun main() { val settings = Settings() val store = BenchmarkSqlStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") - val engine = NettyEpollServerAdapter() + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") + val engine = NettyEpollServerAdapter( + keepAliveHandler = false, + httpAggregatorHandler = false, + chunkedHandler = false, + enableWebsockets = false, + ) val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) benchmark.server.start() diff --git a/frameworks/Kotlin/hexagon/hexagon_nima_pgclient/build.gradle b/frameworks/Kotlin/hexagon/hexagon_nima_pgclient/build.gradle deleted file mode 100644 index 86d2692a326..00000000000 --- a/frameworks/Kotlin/hexagon/hexagon_nima_pgclient/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ - -apply(from: "$gradleScripts/application.gradle") - -dependencies { - api(project(":store_pgclient")) - api("com.hexagonkt:http_server_nima:$hexagonVersion") -} diff --git a/frameworks/Kotlin/hexagon/hexagon_nima_postgresql/src/main/kotlin/Benchmark.kt b/frameworks/Kotlin/hexagon/hexagon_nima_postgresql/src/main/kotlin/Benchmark.kt deleted file mode 100644 index 16e4797e37a..00000000000 --- a/frameworks/Kotlin/hexagon/hexagon_nima_postgresql/src/main/kotlin/Benchmark.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.hexagonkt - -import com.hexagonkt.core.urlOf -import com.hexagonkt.http.server.nima.NimaServerAdapter -import com.hexagonkt.store.BenchmarkSqlStore -import com.hexagonkt.templates.rocker.RockerAdapter - -fun main() { - val settings = Settings() - val store = BenchmarkSqlStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") - val engine = NimaServerAdapter() - - val benchmark = Benchmark(engine, store, templateEngine, templateUrl, settings) - benchmark.server.start() -} diff --git a/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt b/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt index 86e43997145..69fe6d13ba6 100644 --- a/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt +++ b/frameworks/Kotlin/hexagon/hexagon_tomcat_postgresql/src/main/kotlin/WebListenerServer.kt @@ -1,5 +1,6 @@ package com.hexagonkt +import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.urlOf import com.hexagonkt.http.model.Header import com.hexagonkt.http.model.Headers @@ -7,7 +8,7 @@ import com.hexagonkt.http.handlers.HttpHandler import com.hexagonkt.http.handlers.OnHandler import com.hexagonkt.http.server.servlet.ServletServer import com.hexagonkt.store.BenchmarkSqlStore -import com.hexagonkt.templates.rocker.RockerAdapter +import com.hexagonkt.templates.jte.JteAdapter import jakarta.servlet.annotation.WebListener @WebListener class WebListenerServer( @@ -19,8 +20,8 @@ import jakarta.servlet.annotation.WebListener fun createHandlers(settings: Settings): List { val store = BenchmarkSqlStore("postgresql") - val templateEngine = RockerAdapter() - val templateUrl = urlOf("classpath:fortunes.rocker.html") + val templateEngine = JteAdapter(TEXT_HTML, precompiled = true) + val templateUrl = urlOf("classpath:fortunes.jte") val controller = Controller(settings, store, templateEngine, templateUrl) val controllerPath = controller.path val serverHeaderHandler = OnHandler("*") { diff --git a/frameworks/Kotlin/hexagon/settings.gradle b/frameworks/Kotlin/hexagon/settings.gradle index e3acf2270d5..f7b97fb2582 100644 --- a/frameworks/Kotlin/hexagon/settings.gradle +++ b/frameworks/Kotlin/hexagon/settings.gradle @@ -7,8 +7,8 @@ include( "hexagon_jetty_pgclient", "hexagon_jetty_postgresql", - "hexagon_nima_pgclient", - "hexagon_nima_postgresql", + "hexagon_helidon_pgclient", + "hexagon_helidon_postgresql", "hexagon_nettyepoll_pgclient", "hexagon_nettyepoll_postgresql", "hexagon_tomcat_postgresql", diff --git a/frameworks/Kotlin/hexagon/store_pgclient/build.gradle b/frameworks/Kotlin/hexagon/store_pgclient/build.gradle index 6d0c88ad20e..101c965aa6b 100644 --- a/frameworks/Kotlin/hexagon/store_pgclient/build.gradle +++ b/frameworks/Kotlin/hexagon/store_pgclient/build.gradle @@ -2,5 +2,4 @@ dependencies { api(project(":core")) implementation("io.vertx:vertx-pg-client:$vertxVersion") - implementation("com.ongres.scram:client:2.1") } diff --git a/frameworks/PHP/swoole/php.ini b/frameworks/PHP/swoole/php.ini index 58f4ab34b00..99a548fe57e 100644 --- a/frameworks/PHP/swoole/php.ini +++ b/frameworks/PHP/swoole/php.ini @@ -1,6 +1,9 @@ +opcache.enable=1 opcache.enable_cli=1 opcache.validate_timestamps=0 -memory_limit = 1024M +opcache.enable_file_override=1 +opcache.huge_code_pages=1 +memory_limit=1024M opcache.jit_buffer_size=128M opcache.jit=tracing diff --git a/frameworks/Pascal/mormot/benchmark_config.json b/frameworks/Pascal/mormot/benchmark_config.json index 1e71c4ea176..10bbf278270 100644 --- a/frameworks/Pascal/mormot/benchmark_config.json +++ b/frameworks/Pascal/mormot/benchmark_config.json @@ -1,5 +1,6 @@ { "framework": "mormot", + "maintainers": ["pavelmash", "synopse"], "tests": [ { "default": { diff --git a/frameworks/Pascal/mormot/setup_and_build.sh b/frameworks/Pascal/mormot/setup_and_build.sh index 5126df5d967..9afe8eff833 100755 --- a/frameworks/Pascal/mormot/setup_and_build.sh +++ b/frameworks/Pascal/mormot/setup_and_build.sh @@ -27,7 +27,7 @@ rm -rf ./libs mkdir -p ./libs/mORMot/static # echo "Getting the latest pre-release URL..." # USED_TAG=$(wget -qO- https://api.github.com/repos/synopse/mORMot2/releases/latest | jq -r '.tag_name') -USED_TAG="2.0.stable" +USED_TAG="2.1.stable" echo "Used release tag $USED_TAG" URL="https://github.com/synopse/mORMot2/releases/download/$USED_TAG/mormot2static.tgz" @@ -35,7 +35,7 @@ echo "Download statics from $URL ..." wget -qO- "$URL" | tar -xz -C ./libs/mORMot/static # uncomment for fixed commit URL -URL=https://github.com/synopse/mORMot2/tarball/139b61c77065d0b7c784eeeec8217c7e4dbb9618 +URL=https://github.com/synopse/mORMot2/tarball/c9cefa05e892763ff66a9a51a659b937def36195 #URL="https://api.github.com/repos/synopse/mORMot2/tarball/$USED_TAG" echo "Download and unpacking mORMot sources from $URL ..." wget -qO- "$URL" | tar -xz -C ./libs/mORMot --strip-components=1 diff --git a/frameworks/Python/django/requirements.txt b/frameworks/Python/django/requirements.txt index 5eea13caf49..a337c00f8d9 100644 --- a/frameworks/Python/django/requirements.txt +++ b/frameworks/Python/django/requirements.txt @@ -1,4 +1,4 @@ -Django==3.2.20 +Django==3.2.23 mysqlclient==1.4.6 psycopg2==2.9.6; implementation_name=='cpython' psycopg2cffi==2.9.0; implementation_name=='pypy' diff --git a/frameworks/Python/emmett/app.py b/frameworks/Python/emmett/app.py index 27ac74a4868..50a942ce7ad 100644 --- a/frameworks/Python/emmett/app.py +++ b/frameworks/Python/emmett/app.py @@ -86,8 +86,8 @@ async def fortunes(): async def updates(): num_queries = get_qparam() updates = list(zip( - sample(range(1, 10000), num_queries), - sorted(sample(range(1, 10000), num_queries)) + sorted(sample(range(1, 10000), num_queries)), + sample(range(1, 10000), num_queries) )) worlds = [] for row_id, number in updates: diff --git a/frameworks/Python/emmett/emmett.dockerfile b/frameworks/Python/emmett/emmett.dockerfile index 6665b8efb02..d4b2b87702f 100644 --- a/frameworks/Python/emmett/emmett.dockerfile +++ b/frameworks/Python/emmett/emmett.dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.11-slim ADD ./ /emmett diff --git a/frameworks/Python/emmett/run.py b/frameworks/Python/emmett/run.py index 4c7e404cd81..658eadb7d5f 100644 --- a/frameworks/Python/emmett/run.py +++ b/frameworks/Python/emmett/run.py @@ -16,6 +16,5 @@ backlog=2048, threading_mode='runtime', enable_websockets=False, - loop_opt=True, log_level="warn" ) diff --git a/frameworks/Python/granian/granian-rsgi.dockerfile b/frameworks/Python/granian/granian-rsgi.dockerfile index 315493dc7ca..d84b713044b 100644 --- a/frameworks/Python/granian/granian-rsgi.dockerfile +++ b/frameworks/Python/granian/granian-rsgi.dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.11-slim ADD ./ /granian diff --git a/frameworks/Python/granian/granian-wrk.dockerfile b/frameworks/Python/granian/granian-wrk.dockerfile index 533a5bc722a..2f56af92d53 100644 --- a/frameworks/Python/granian/granian-wrk.dockerfile +++ b/frameworks/Python/granian/granian-wrk.dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.11-slim ADD ./ /granian diff --git a/frameworks/Python/granian/granian.dockerfile b/frameworks/Python/granian/granian.dockerfile index 828808b1009..883c433f3f0 100644 --- a/frameworks/Python/granian/granian.dockerfile +++ b/frameworks/Python/granian/granian.dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.11-slim ADD ./ /granian diff --git a/frameworks/Python/granian/requirements.txt b/frameworks/Python/granian/requirements.txt index 00f480f3c21..601bdc3e401 100644 --- a/frameworks/Python/granian/requirements.txt +++ b/frameworks/Python/granian/requirements.txt @@ -1,4 +1,4 @@ asyncpg==0.27.0 -granian>=0.5.0,<0.6.0 +granian>=0.7.0,<0.8.0 jinja2==3.1.2 -orjson==3.8.1 +orjson==3.9.10 diff --git a/frameworks/Python/granian/run.py b/frameworks/Python/granian/run.py index d3bff3a1d51..a81600ef9cd 100644 --- a/frameworks/Python/granian/run.py +++ b/frameworks/Python/granian/run.py @@ -20,6 +20,5 @@ backlog=2048, interface=interface, http="1", - websockets=False, - loop_opt=True + websockets=False ).serve() diff --git a/frameworks/Ruby/padrino/config/auto_tune.rb b/frameworks/Ruby/padrino/config/auto_tune.rb new file mode 100644 index 00000000000..4544231b9d2 --- /dev/null +++ b/frameworks/Ruby/padrino/config/auto_tune.rb @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby +# Instantiate about one process per X MiB of available memory, scaling up to as +# close to MAX_THREADS as possible while observing an upper bound based on the +# number of virtual/logical CPUs. If there are fewer processes than +# MAX_THREADS, add threads per process to reach MAX_THREADS. +require 'etc' + +KB_PER_WORKER = 128 * 1_024 # average of peak PSS of single-threaded processes (watch smem -k) +MIN_WORKERS = 2 +MAX_WORKERS_PER_VCPU = 1.25 # virtual/logical +MIN_THREADS_PER_WORKER = 1 +MAX_THREADS = Integer(ENV['MAX_CONCURRENCY'] || 8) + +def meminfo(arg) + File.open('/proc/meminfo') do |f| + f.each_line do |line| + key, value = line.split(/:\s+/) + return value.split(/\s+/).first.to_i if key == arg + end + end + + fail "Unable to find `#{arg}' in /proc/meminfo!" +end + +def auto_tune + avail_mem = meminfo('MemAvailable') * 0.8 - MAX_THREADS * 1_024 + + workers = [ + [(1.0 * avail_mem / KB_PER_WORKER).floor, MIN_WORKERS].max, + (Etc.nprocessors * MAX_WORKERS_PER_VCPU).ceil + ].min + + threads_per_worker = [ + workers < MAX_THREADS ? (1.0 * MAX_THREADS / workers).ceil : -Float::INFINITY, + MIN_THREADS_PER_WORKER + ].max + + [workers, threads_per_worker] +end + +p auto_tune if $0 == __FILE__ diff --git a/frameworks/Ruby/padrino/config/puma.rb b/frameworks/Ruby/padrino/config/puma.rb index a4adcc8ded8..8a42642fd61 100644 --- a/frameworks/Ruby/padrino/config/puma.rb +++ b/frameworks/Ruby/padrino/config/puma.rb @@ -1,3 +1,9 @@ +require_relative 'auto_tune' + +num_workers, num_threads = auto_tune + +workers num_workers +threads num_threads, num_threads + environment 'production' -threads 8, 32 -bind 'tcp://0.0.0.0:8080' \ No newline at end of file +bind 'tcp://0.0.0.0:8080' diff --git a/frameworks/Ruby/padrino/config/unicorn.rb b/frameworks/Ruby/padrino/config/unicorn.rb index fa84460c73d..9ca3171328b 100644 --- a/frameworks/Ruby/padrino/config/unicorn.rb +++ b/frameworks/Ruby/padrino/config/unicorn.rb @@ -1,4 +1,8 @@ -worker_processes 8 +require_relative 'auto_tune' + +num_workers, = auto_tune + +worker_processes num_workers listen "/tmp/.sock", :backlog => 4096 preload_app true diff --git a/frameworks/Ruby/rack/benchmark_config.json b/frameworks/Ruby/rack/benchmark_config.json index c5190465d38..8e2f5884387 100644 --- a/frameworks/Ruby/rack/benchmark_config.json +++ b/frameworks/Ruby/rack/benchmark_config.json @@ -7,6 +7,7 @@ "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", + "fortune_url": "/fortunes", "update_url": "/updates?queries=", "port": 8080, "approach": "Stripped", @@ -27,6 +28,7 @@ "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", + "fortune_url": "/fortunes", "update_url": "/updates?queries=", "port": 8080, "approach": "Stripped", @@ -47,6 +49,7 @@ "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", + "fortune_url": "/fortunes", "update_url": "/updates?queries=", "port": 8080, "approach": "Stripped", @@ -67,6 +70,7 @@ "plaintext_url": "/plaintext", "db_url": "/db", "query_url": "/queries?queries=", + "fortune_url": "/fortunes", "update_url": "/updates?queries=", "port": 8080, "approach": "Stripped", diff --git a/frameworks/Ruby/rack/hello_world.rb b/frameworks/Ruby/rack/hello_world.rb index 95c9075dcae..d6886797fc0 100644 --- a/frameworks/Ruby/rack/hello_world.rb +++ b/frameworks/Ruby/rack/hello_world.rb @@ -41,7 +41,7 @@ class HelloWorld TEMPLATE_PREFIX = ' - Fortune + Fortunes @@ -50,7 +50,7 @@ class HelloWorld ' TEMPLATE_POSTFIX = '
message
- ' def initialize @@ -66,8 +66,7 @@ def respond(content_type, body = '') CONTENT_TYPE => content_type, DATE => Time.now.utc.httpdate, SERVER => SERVER_STRING, - CONTENT_LENGTH => body.length.to_s - + CONTENT_LENGTH => body.bytesize.to_s }, [body] ] @@ -81,7 +80,7 @@ def fortunes buffer << TEMPLATE_PREFIX fortunes.each do |item| - buffer << " #{item[:id]} #{Rack::Utils.escape_html(item[:message])}" + buffer << "#{item[:id]}#{Rack::Utils.escape_html(item[:message])}" end buffer << TEMPLATE_POSTFIX end diff --git a/frameworks/Ruby/rails/config/auto_tune.rb b/frameworks/Ruby/rails/config/auto_tune.rb index 17853247174..703b5bbe731 100644 --- a/frameworks/Ruby/rails/config/auto_tune.rb +++ b/frameworks/Ruby/rails/config/auto_tune.rb @@ -6,7 +6,7 @@ require 'etc' KB_PER_WORKER = 128 * 1_024 # average of peak PSS of single-threaded processes (watch smem -k) -MIN_WORKERS = 15 +MIN_WORKERS = 2 MAX_WORKERS_PER_VCPU = 1.25 # virtual/logical MIN_THREADS_PER_WORKER = 1 MAX_THREADS = Integer(ENV['MAX_CONCURRENCY'] || 256) diff --git a/frameworks/Ruby/rails/config/database.yml b/frameworks/Ruby/rails/config/database.yml index ae7de0910d7..8fa7b78a4e1 100644 --- a/frameworks/Ruby/rails/config/database.yml +++ b/frameworks/Ruby/rails/config/database.yml @@ -5,7 +5,7 @@ default: &default password: benchmarkdbpass host: tfb-database timeout: 5000 - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + pool: <%= require_relative 'auto_tune'; auto_tune.reduce(:*) %> development: <<: *default diff --git a/frameworks/Rust/roa/roa-core.dockerfile b/frameworks/Rust/roa/roa-core.dockerfile index ce2fd1e0723..e77098a5a32 100644 --- a/frameworks/Rust/roa/roa-core.dockerfile +++ b/frameworks/Rust/roa/roa-core.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/roa/roa-diesel.dockerfile b/frameworks/Rust/roa/roa-diesel.dockerfile index effe77c5c04..35d7aa3507a 100644 --- a/frameworks/Rust/roa/roa-diesel.dockerfile +++ b/frameworks/Rust/roa/roa-diesel.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/roa/roa-pg.dockerfile b/frameworks/Rust/roa/roa-pg.dockerfile index d0a93934630..beb9d673858 100644 --- a/frameworks/Rust/roa/roa-pg.dockerfile +++ b/frameworks/Rust/roa/roa-pg.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/roa/roa-sqlx.dockerfile b/frameworks/Rust/roa/roa-sqlx.dockerfile index bb2468f68f8..f14a42dc735 100644 --- a/frameworks/Rust/roa/roa-sqlx.dockerfile +++ b/frameworks/Rust/roa/roa-sqlx.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/roa/roa-tokio.dockerfile b/frameworks/Rust/roa/roa-tokio.dockerfile index 93a266e10f5..38f3b9fa381 100644 --- a/frameworks/Rust/roa/roa-tokio.dockerfile +++ b/frameworks/Rust/roa/roa-tokio.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/roa/roa.dockerfile b/frameworks/Rust/roa/roa.dockerfile index 1d330eef042..29ed4e2200f 100644 --- a/frameworks/Rust/roa/roa.dockerfile +++ b/frameworks/Rust/roa/roa.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.59.0 +FROM rust:1.73 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/viz/src/db_pg.rs b/frameworks/Rust/viz/src/db_pg.rs index 517163ee7c3..672925e3d5a 100644 --- a/frameworks/Rust/viz/src/db_pg.rs +++ b/frameworks/Rust/viz/src/db_pg.rs @@ -160,21 +160,25 @@ impl PgConnection { } pub async fn tell_fortune(&self) -> Result, PgError> { - let mut items = self + let mut items = vec![Fortune { + id: 0, + message: Cow::Borrowed("Additional fortune added at request time."), + }]; + + let stream = self .client - .query(&self.fortune, &[]) - .await? - .iter() - .map(|row| Fortune { + .query_raw::<_, _, &[i32; 0]>(&self.fortune, &[]) + .await?; + pin!(stream); + + while let Some(row) = stream.next().await { + let row = row?; + + items.push(Fortune { id: row.get(0), message: Cow::Owned(row.get(1)), - }) - .collect::>(); - - items.push(Fortune { - id: 0, - message: Cow::Borrowed("Additional fortune added at request time."), - }); + }); + } items.sort_by(|it, next| it.message.cmp(&next.message));