Grpc передает большие данные, один унарный вызов медленнее, чем потоковая передача,

#c# #.net #grpc

#c# #.net #grpc

Вопрос:

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

Размер данных составляет около 23 миллионов и состоит из 42 больших списков.

Затем я тестирую производительность, используя один унарный вызов против потоковой передачи на стороне сервера (поток по одному списку за раз).

Унарный вызов занимает 276,59 мс.

Потоковый вызов занимает 126,64 мс.

Но если я изменю данные на 1000 небольших списков, в каждом списке будет только один номер, потоковый вызов будет намного медленнее, чем унарный вызов.

Является ли результат нормальным? И почему?

Вот код на стороне сервера:

 public override Task<MemDtoToWbs> GetLargeMEM(Empty request, ServerCallContext context)
{
    return Task.FromResult(MemData.GrpcLargeMem);
}
public override async Task StreamLargeMem(Empty request, IServerStreamWriter<LogDtoToWbs> responseStream, ServerCallContext context)
{
    foreach (var log in MemData.GrpcLargeMem.Logs)
    {
         await responseStream.WriteAsync(log);
    }
}
  

Я использую .net core 3.1 и пакет grpc nuget 2.32.0.
Запустите тест в кластере aks.

Спасибо.

Комментарии:

1. Что ж, именно поэтому, говоря о производительности, вы можете услышать фразу «все является компромиссом». Нет единого наилучшего подхода, каждая ситуация требует выполнения определенных действий определенным образом.

2. Спасибо @CamiloTerevinto за ответ. Но я хочу знать, что вызвало такую разницу.

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

Ответ №1:

Я думаю, что @Ян Таттермуш прав.

Я тестирую на локальном хосте, размер сегмента TCP составляет 64 КБ. Когда небольшие сообщения слишком малы, например, 32 КБ, они имеют длину полезной нагрузки всего 6,5 Тыс. В каждом сегменте TCP. Но если сообщение большое, оно может использовать все 64 КБ. Так что да, накладные расходы на отправку каждого сообщения могут складываться, и все может закончиться медленнее.

Поэтому для меня разумно, что потоковая передача выполняется быстрее, если сообщение большое. Поскольку отправка данных на стороне сервера и обработка данных на стороне клиента выполняются параллельно.

введите описание изображения здесь