ASP. Net Ответ Core API занимает слишком много времени - PullRequest
2 голосов
/ 27 апреля 2020

У меня есть SQL таблица базы данных с 9000 строками и 97 столбцами. Его первичный ключ имеет 2 столбца: Color и Name. Вы можете увидеть упрощенную таблицу, чтобы изображение лучше:

enter image description here

У меня есть ASP. NET Базовое API, прослушивающее URL-адрес api/color/{colorName}, оно читает таблицу, чтобы получить информация о цвете. В настоящее время у меня есть 3 цвета и около 3000 строк в каждом.

Это занимает слишком много времени. Он читает таблицу за 2383 мс и отображает DTO за 14 мс. И после этого я немедленно возвращаю DTO потребителю, но каким-то образом API занимает 4135,422 мс. Я не понимаю почему. Я думаю, что я должен взять 2407.863ms, но это не так. Это занимает почти в 2 раза больше.

Вы можете увидеть мой код и журналы ниже. У вас есть идея, как я могу улучшить время отклика?

Я использую Entity Framework Core 3.1, AutoMapper и ASP. NET Core 3.1.

Сервис:

public async Task<IEnumerable<ColorDTO>> GetColors(string requestedColor)
{
    var watch = System.Diagnostics.Stopwatch.StartNew();
    var colors = await _dbContext.Colors.Where(color => color.color == requestedColor).ToListAsync();
    watch.Stop();
    _logger.LogError("Color of:{requestedColor} Reading takes:{elapsedMs}", requestedColor, watch.ElapsedMilliseconds);


    var watch2 = System.Diagnostics.Stopwatch.StartNew();
    var colorDtos = _mapper.Map<IEnumerable<ColorDTO>>(colors);
    watch2.Stop();
    _logger.LogError("Color of:{requestedColor} Mapping takes:{elapsedMs}", requestedColor, watch2.ElapsedMilliseconds);

    return colorDtos;
}

Контроллер:

public async Task<ActionResult<IEnumerable<ColorDTO>>> GetBlocksOfPanel(string requestedColor)
{
    return Ok(await _colorService.GetColors(requestedColor));
}

И журналы:

2020-04-27 15:21:54.8793||0HLVAKLTJO59T:00000003|MyProject.Api.Services.IColorService|INF|Color of Purple Reading takes:2383ms
2020-04-27 15:21:54.8994||0HLVAKLTJO59T:00000003|MyProject.Api.Services.IColorService|INF|Color of Purple Mapping takes:14ms
2020-04-27 15:21:54.9032||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|INF|Executed action method MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web), returned result Microsoft.AspNetCore.Mvc.OkObjectResult in 2407.863ms.
2020-04-27 15:21:54.9081||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor|INF|Executing ObjectResult, writing value of type 'System.Collections.Generic.List`1[[MyProject.Api.Contracts.Dtos.ColorDTO, MyProject.Api.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
2020-04-27 15:21:56.4895||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|INF|Executed action MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web) in 4003.8022ms
2020-04-27 15:21:56.4927||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Routing.EndpointMiddleware|INF|Executed endpoint 'MyProject.Api.Web.Controllers.ColorsController.GetColors (MyProject.Api.Web)'
2020-04-27 15:21:56.4972||0HLVAKLTJO59T:00000003|Microsoft.AspNetCore.Hosting.Diagnostics|INF|Request finished in 4135.422ms 200 application/json; charset=utf-8

Ответы [ 2 ]

1 голос
/ 27 апреля 2020

Как упомянул @ejwill в своем комментарии, вы должны учитывать задержку во всей операции. Извлечение из базы данных и сопоставление с DTO - это только часть того, что происходит во время прохождения запроса и ответа на ваш API.

Вероятно, вы можете сократить время запроса к вашей таблице базы данных путем некоторой оптимизации там , Вы не указываете, какую базу данных вы используете, но составной ключ, основанный на двух значениях string / varchar, не обязательно может быть наиболее производительным, и использование индексов для значений, по которым вы фильтруете, также может помочь - есть компромиссы там в зависимости от того, оптимизируете ли вы для записи или для чтения. При этом 97 столбцов не тривиально в любом случае. Вам нужно запросить и вернуть все 97 столбцов через API? Разрешается ли разбивка на страницы?

Если вам необходимо вернуть все данные сразу для всех 97 столбцов, и вы часто запрашиваете API, вы также можете рассмотреть возможность использования кэша в памяти, особенно если таблица не часто меняется; вместо того, чтобы каждый раз обращаться к базе данных, вы сохраняете копию данных в памяти, чтобы их можно было вернуть намного быстрее. Вы можете посмотреть на реализацию кэша в памяти, который поддерживает модель поколений, чтобы продолжать обслуживать данные, пока выбираются новые версии.

https://github.com/jfbosch/recache

0 голосов
/ 28 апреля 2020

Сериализация результата может занять огромное время.

Первое - это сама сериализация: если вы вернете записи 3k, сериализации потребуется JSON или XML. Подумайте о переходе на более компактные двоичные форматы.

Второе - это память и G C. Если количество сериализованных данных превышает 85 000 байтов, память для этих данных будет выделена на LOH в одном фрагменте. Это может занять время. Вы можете рассмотреть возможность проверки вашего LOH и найти данные ответов, хранящиеся там. Возможный обходной путь может заключаться в ответе кусками данных и использованием вида подкачки с offset и position.

. Вы можете легко проверить, что сериализация вызывает проблемы с производительностью: оставить вызов БД как есть, но вернуть клиенту только 100-200 строк вместо целого результата или возврат меньше полей объекта (например, только 3). Время должно быть сокращено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...