2017-01-24 2 views
2

Vielleicht habe ich den Punkt von Protobufs etwas verpasst, aber ich habe etwas Zeit investiert, um es umzusetzen, weil ich gehofft hatte, roh zu werden Geschwindigkeit im Vergleich zu meinem aktuellen JSON-Setup.JSON ist viel schneller als Protobuf/gRPC für mich, mit Go als Server und PHP als Client

Mein Anwendungsfall ist so: eine große, komplizierte PHP-Anwendung (keine Website), in Produktion und wird stark verwendet. Wir versuchen nun, unsere Anwendung in kleinere Teile aufzuteilen, die für jedes Problem in einer geeigneten Sprache geschrieben sind. Der erste Service, den ich aufgeteilt habe, ist die Verarbeitung und Transformation von Strings, sehr Domain-spezifisch und nicht sehr interessant. Beinhaltet viele Regex, benutzerdefinierte Parsing usw.

Ich implementiert meine Domain-Logik in Go, die sehr schön funktioniert und war sehr einfach zu erlernen. Ich habe meine Logik mithilfe von Go-Kit an eine einfache JSON-API angefügt. Ist eine sehr einfache Transformation, JSON-Codierung einfach zu etwas wie {"v": "einige Zeichenfolge in der Regel 10-100 Zeichen"}.

Die Leistung war schlechter als natives PHP, was ich unter Berücksichtigung des Overheads von JSON und der zusätzlichen Übertragung über eine Netzwerkschicht für durchaus akzeptabel halte.

Was mich jedoch wirklich überrascht hat ist, dass Protobuf nicht nur nicht schneller als JSON, sondern tatsächlich um 30-50% langsamer war.

Mein .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; 
} 

I verwendet https://github.com/stanley-cheung/Protobuf-PHP und die erzeugte proto PHP-Code. Mein PHP-Client-Code ist wie folgt:

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

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

Es funktioniert, aber zu meiner Überraschung ist es viel langsamer als JSON.

Meine einzige Vermutung: ist es möglich, die PHP-Implementierung von Protobufs ist so viel langsamer als json_decode, die derzeit PHP macht einen sehr schlechten Client für Protobuf?

Oder ist es normal für kleine, einfache Anwendungen wie das Übertragen einer einzelnen Zeichenfolge, die JSON Protobuf ausführen soll?

Vielen Dank für alle Gedanken.

+0

Dies ist eine [große Bibliothek] (https://github.com/stanley-cheung/Protobuf-PHP/) in PHP geschrieben, während 'json_encode' in C++ geschrieben ist und seit der ersten Verwendung von Millionen verwendet und optimiert wurde . 'json_encode' wird um ein Vielfaches schneller sein als jedes andere PHP-basierte Packsystem. – Xeoncross

+0

Danke, das war meine Vermutung und es macht sehr viel Sinn. Das Abwägen der Vor- und Nachteile von Protobufs ist komplizierter, weil PHP am Ende nicht der einzige Client ist. Aus Ihrer Erfahrung gibt es in diesem exakten Anwendungsfall eine schnellere Art der Übertragung als JSON? – mhsc

+0

BSON ist kompakter und wird von mehreren Datenbank-Engines verwendet. Obwohl es nur binary JSON ist, unterstützt es keine Schemas wie Protobufs. – Xeoncross

Antwort

2

Die native PHP Implementierung von protobuf, die Sie mit composer require google/protobuf installieren ist viel langsamer als dieprotobuf C extension. Um eine wirkliche Leistung zu erhalten aus gRPC müssen Sie die protobuf C-Erweiterung installieren:

pecl install protobuf 

und ermöglichen es in php.ini

extension=protobuf.so 

Dies macht die ganze Serialisierung/Deserialisierung in C statt in PHP, Das wird viel schneller sein als die PHP-Version.

Verwandte Themen