JSON для меня намного быстрее, чем Protobuf / gRPC, с Go в качестве сервера и PHP в качестве клиента

Возможно, я несколько упустил суть Protobufs, но я потратил некоторое время на его реализацию, потому что надеялся получить чистую скорость по сравнению с моей текущей настройкой JSON.

Мой вариант использования такой: большое сложное приложение PHP (не веб-сайт) находится в стадии разработки и активно используется. Теперь мы пытаемся разбить наше приложение на более мелкие части, написанные на подходящем языке для каждой проблемы. Первый выделенный мною сервис выполняет обработку и преобразование строк, очень специфичных для предметной области и не очень интересных. Включает в себя множество регулярных выражений, пользовательский синтаксический анализ и т. Д.

Я реализовал логику своей предметной области в Go, которая прекрасно работает и ее очень легко освоить. Я привязал свою логику к простому JSON API, используя Go-Kit. Это очень простое преобразование, кодирование json просто до чего-то вроде {"v": "какая-то строка обычно 10-100 символов"}.

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

Однако что меня действительно удивило, так это то, что Protobuf не только не быстрее JSON, но и на 30-50% медленнее.

Мой .proto:

syntax = "proto3";

package pb;

option optimize_for = SPEED;

service StringStuff {
  rpc DoStringStuff (StringReq) returns (StringRes) {}
}

message StringReq {
  string in = 1;
}

message StringRes {
  string out = 1;
}

Я использовал https://github.com/stanley-cheung/Protobuf-PHP и сгенерированный код proto php. Мой код клиента php выглядит так:

$client = new StringClient('localhost:50051', [
'credentials' => \Grpc\ChannelCredentials::createInsecure()]);

$string = new StringReq();
$string->setIn("some string...");
list($reply, $status) = $client->DoStringStuff($string)->wait();

Это работает, но, к моему удивлению, намного медленнее, чем JSON.

Мое единственное предположение: возможно ли, что реализация Protobufs на php настолько медленнее, чем json_decode, что в настоящее время PHP является очень плохим клиентом для Protobuf?

Или это нормально для небольших, простых применений, таких как передача одной строки, которую JSON должен превзойти, выполняя Protobuf?

Спасибо за любые мысли.


person mhsc    schedule 24.01.2017    source источник
comment
Это большая библиотека, написанная на PHP, а json_encode написана на C ++ и была используется миллионами и оптимизирован с момента первого добавления. json_encode будет во много раз быстрее, чем любая система упаковки на основе PHP.   -  person Xeoncross    schedule 25.01.2017
comment
Спасибо, это было мое предположение, и это имеет большой смысл. Взвешивать плюсы и минусы Protobufs сложнее, потому что, в конце концов, PHP не будет единственным клиентом. Исходя из вашего опыта, есть ли более быстрый способ передачи в этом конкретном случае использования, чем JSON?   -  person mhsc    schedule 25.01.2017
comment
BSON более компактен и используется несколькими механизмами баз данных. Хотя это просто двоичный JSON, поэтому он не поддерживает схемы, такие как Protobufs.   -  person Xeoncross    schedule 25.01.2017
comment
Как вы проводите сравнительный анализ? Известно, что получение точных и правдоподобных результатов тестов является сложной задачей.   -  person Carl Mastrangelo    schedule 25.01.2017
comment
Что именно сравниваете? Если вы просто посмотрите на один вызов, то JSON с необработанным tcp будет быстрее, чем Grpc / Protobuf с http2 в качестве дополнительных накладных расходов. Grpc будет сиять и, скорее всего, превзойдет JSON при просмотре потоковой передачи и многих сообщений / вызовов.   -  person weismat    schedule 25.01.2017
comment
В моем тесте использовалось микровремя php для расчета разницы во времени в конце последовательности вызовов и времени до него. Я пробовал для 1, 10, 100, 1000, 10 000 и 100 000 звонков. CURL с декодированием JSON (расширение C ++, как описано выше) всегда был быстрее, чем Protobuf / gRPC. Я много возился, пытаясь найти способ сделать Protobufs быстрее, хотя бы один раз, думая, что мой тест просто ненадежен. Но ни в коем случае я не мог заставить его работать быстрее или даже сравнимо.   -  person mhsc    schedule 25.01.2017
comment
Это имеет смысл, особенно если ваши приложения размещены в сети с хорошей пропускной способностью. Protobuf выполняет сжатие, которое отлично снижает пропускную способность, но за счет циклов ЦП. JSON должен занимать больше полосы пропускания, но меньше циклов ЦП для десериализации, чем Protobuf. Итак, пока сеть не перегружена, JSON должен превзойти Protobuf по скорости.   -  person Liam Kelly    schedule 25.01.2017
comment
Protobuf поддерживает расширение php c: pecl.php.net/package/protobuf   -  person TeBoring    schedule 09.02.2017


Ответы (1)


Собственная реализация PHP protobuf, которую вы устанавливаете с composer require google/protobuf, намного медленнее, чем protobuf C расширение. Чтобы получить реальную производительность от gRPC, вам необходимо установить расширение protobuf C:

pecl install protobuf

и включите его в php.ini

extension=protobuf.so

Это делает всю сериализацию / десериализацию на C, а не на PHP, который будет во много раз быстрее, чем версия PHP.

person Brent Shaffer    schedule 13.06.2017