Трудно сказать точно, где ваша программа становится узким местом без дополнительных данных (например, флеймографов и т. Д.).
Видя, как это происходит, когда вы переключаете сервер gRPC на прослушивание одного порта, я могу сделать некоторые предположения относительно того, где происходит замедление. Похоже, вы запрашиваете вызов на стороне сервера в верхней части цикла продолжения ( 1 ). Я бы посоветовал для другого шаблона; запросите некоторое фиксированное количество вызовов (в сотнях), затем в конце цикла обработчика повторно запросите вызов, чтобы сервер всегда был «подготовлен» для получения множества входящих RPC.
И пример этого шаблона можно найти в нашем коде драйвера QPS (точно настроенное, высоко оптимизированное приложение для тестирования производительности) ( 2 ).
TF также делает это таким образом ( 3 ).
Кроме того, просто несколько небольших выборочных проверок, когда я читаю ваш код. Есть некоторые места, которые вы могли бы подумать о настройке, чтобы получить лучшие номера. Например, вам может потребоваться выделить только один раз ( 4 ), чтобы избежать сравнительного анализа повторных вызовов malloc для каждого RPC. Кроме того, почему вы делаете пользовательскую сериализацию для байтового буфера здесь ( 5 )? Это может упустить специфичные для прото-оптимизации.