Низкая производительность в Kestrel по сравнению с IIS - PullRequest
0 голосов
/ 17 мая 2018

Для демонстрации я собираюсь запустить тест, в котором я сравниваю .NET Core, работающий на Kestrel, и .NET Framework 4.6.1, работающий на IIS. Оба на локальной машине.

«Интернет» говорит, что Kestrel намного быстрее, но в моем собственном тесте нет заметного различия с IIS. И большую часть времени IIS еще быстрее. Как это?

У меня «тот же» код, работающий на .NET Framework (с использованием EF) и .NET Core (с использованием EFCore). controller выглядит следующим образом. Он что-то записывает в БД, а затем извлекает и возвращает. Я закрываю DBContext, чтобы убедиться, что кеша нет. Код для .NET Core ниже (код для .NET Framework аналогичен, кроме DI).

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly DbContextOptions<DemoContext> options;

    public ValuesController(DbContextOptionsBuilder<DemoContext> builder)
    {
        this.options = builder.Options;
    }

    // GET api/values
    [HttpGet]
    public async Task<IActionResult> Get()
    {
        var id = Guid.NewGuid();
        using (var context = new DemoContext(options))
        {

            var newItem = new DemoTable()
            {
                Id = id,
                Stamp = DateTime.Now,
                System = "Core"
            };
            context.DemoTable.Add(newItem);
            await context.SaveChangesAsync();
        }

        using (var context = new DemoContext(options))
        {
            var item = await context.DemoTable.SingleAsync(x => x.Id == id);
            return Ok(item);

        }
    }
}

Мой Program.cs выглядит так:

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseKestrel(options =>
        {
            options.Limits.MaxConcurrentConnections = 1000;
            options.Listen(IPAddress.Loopback, 5050);
        })
        .ConfigureLogging((context, logging) =>
        {
            logging.ClearProviders();
        })
        .UseStartup<Startup>()
        .Build();

Я запускаю его с dotnet как dotnet demoApp.dll.

Я тестирую его с помощью приложения, которое делает несколько запросов.

    var cts = new CancellationTokenSource();
    int processed = 0;
    int seconds = 30;

    var url = new Uri($"http://localhost:{port}");
    var tasks = new Task[20];
    for (int i = 0; i < tasks.Length; i++)
    {
        tasks[i] = Task.Factory.StartNew(() =>
        {
            while (!token.IsCancellationRequested)
            {
                var client = new RestClient(url);
                var request = new RestRequest("/api/values");
                client.ExecuteAsyncGet(request, (response, handle) =>
                {
                    if(!token.IsCancellationRequested)
                        Interlocked.Add(ref processed, 1);
                }, "GET");
            }
        });
    }
    Thread.Sleep(seconds * 1000);
    cts.Cancel();

Когда я запускаю его на .NET Framework с IIS, я получаю больше запросов, чем на ядре с Kestrel.

Я пытался изменить options.Limits в Kestrel безуспешно. Я предполагаю, что что-то не так с моим «приложением для тестирования» или что мое локальное устройство само является узким местом.

Почему IIS обрабатывает запросы намного быстрее, чем Kestrel?

UPDATE:

Если я уберу EF и верну только OK() в контроллере, IIS все равно будет работать лучше.

Я пробуждаю серверы перед сравнительным тестированием.

Я строю это как Release.

Когда я запускаю с 10 потоками в течение 30 секунд, IIS будет обрабатывать 600 запросов, а запросы Kestrel 300.

gcServer установлено на true.

1 Ответ

0 голосов
/ 02 июля 2018

Вы не можете протестировать производительность веб-хостов, подключив ее к БД. Узким местом будет БД или ваша бизнес-логика.

Начните с чистого проекта или, что еще лучше, просто возьмите эталонный тест. Для высокой производительности многие вещи вступают в игру ..

Тот факт, что вы обрабатываете 300 или 600 запросов (жалко), предполагает что-то еще в конвейере. Обратите внимание, что ваш контроллер также вводит контекст db для каждого запроса + любое промежуточное программное обеспечение, которое у вас есть.

...