Skip to content

Http server performance regression in net6 preview 7 #57656

Description

@hanabi1224

Description

I have a small benchmark program that runs fast with netcore3.1, net5, net6 preview6 and prior (take 1~5 seconds), but the same program runs super slowly in net6 preview 7 (several minutes ~ infinite)

Configuration

Regression?

I can confirm it works fine on netcore3.1, net5, net6 preview 6 and prior

Data

It takes 1~5 seconds normally but several minutes ~ infinite with net6 preview 7

Analysis

N/A

Code

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

static class Program
{
    private const string MimeType = "application/json";
    private static readonly HttpClient s_client = new HttpClient() { Timeout = TimeSpan.FromSeconds(15) };

    public static async Task Main(string[] args)
    {
        int n;
        if (args.Length < 1 || !int.TryParse(args[0], out n))
        {
            n = 2000;
        }

        var port = 30000 + new Random().Next(10000);
        var server = CreateWebHostBuilder(port).Build();
        using var cts = new CancellationTokenSource();
        _ = Task.Factory.StartNew(() => server.Start(), TaskCreationOptions.LongRunning);
        var sum = 0;
        var api = $"http://localhost:{port}/";
        var tasks = new List<Task<int>>(n);
        for (var i = 1; i <= n; i++)
        {
            tasks.Add(SendAsync(api, i));
        }
        foreach (var task in tasks)
        {
            sum += await task.ConfigureAwait(false);
        }
        Console.WriteLine(sum);
        System.Environment.Exit(0);
    }

    private static async Task<int> SendAsync(string api, int value)
    {
        var payload = JsonConvert.SerializeObject(new Payload { Value = value });
        while (true)
        {
            try
            {
                var content = new StringContent(payload, Encoding.UTF8, MimeType);
                var response = await s_client.PostAsync(api, content).ConfigureAwait(false);
                return int.Parse(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
            }
            catch { }
        }
    }

    private static IWebHostBuilder CreateWebHostBuilder(int port)
    {
        return WebHost.CreateDefaultBuilder()
            .SuppressStatusMessages(true)
            .ConfigureLogging((context, logging) =>
            {
                logging.ClearProviders();
            })
            .UseKestrel(options =>
            {
                options.Limits.MaxRequestBodySize = null;
                options.ListenLocalhost(port);
            })
            .UseStartup<Startup>();
    }
}

public sealed class MyController : Controller
{
    [Route("/")]
    public async Task<int> PostAsync()
    {
        using var sr = new StreamReader(Request.Body);
        var bodyText = await sr.ReadToEndAsync().ConfigureAwait(false);
        var payload = JsonConvert.DeserializeObject<Payload>(bodyText);
        return payload.Value;
    }
}

public class Payload
{
    [JsonProperty("value")]
    public int Value { get; set; }
}

public sealed class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvcCore().AddApplicationPart(Assembly.GetExecutingAssembly());
    }

    public void Configure(
        IApplicationBuilder app,
        IWebHostEnvironment env)
    {
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions