Różnica w szybkości przesyłania danych WebApi vs gRPC

1

Cześć,
gRPC umożliwia nawet kilkukrotnie szybsze przesyłanie danych niż zwykłe WebApi. Moje pytanie jest dlaczego tak się dzieje?
Dane w obu przypadkach powinny być przesyłane z prędkością w okolicach prędkości światła. Więc skąd te różnice?
W gRPC dane przesyłane są binarnie, ale jeśli przesyłamy głównie tekst to chyba nie powinno mieć to wpływu na wydajność a wręcz przeciwnie - tekst musimy zamienić na bity/byte'y - więc będzie dodatkowy narzut, czy może się mylę?
Czy może mi ktoś wyjaśnić ten precedens?
W WebApi problemem może być JSON i jego parsowanie, ale zakładając, że dane przesyłam jako tablicę stringów to czy będzie to miało istotny wpływ na wydajność?

2

Oczywiście tak, jest różnica, często ogromna różnica. Zaskoczony ?
Jeśli tak, to tak nam wypruła mózgi monokultura tzw REST / Web API, z rozdziawionymi gębami patrzymy na wynalazek gorszy od tego, co było.
"Wybieramy" Rest/ web API na zasadzie odruchu stadnego baranów, korpo zapłaci za CPU / RAM / routing i pasmo.

Na poziomie roku 2015 tablet odbierający po sieci lokalnej Wifi 300MB/s z webapi a Thritftem (konkurent, bliźniak gRPC) były różnice x3 x8, tu się robił martwy, tam reagował (w domyśle tu klękał CPU i GC, tu nie) Early version testowało HTTP.

WebAPI (za wyjątkiem namiastek na Arduino) leci przez wiele warstw, w każdej jest przetwarzane. Przed danymi JSON leci olbrzymia ilość nagłówków. I znów przez warstwy, a każda swojej dodaje.
Jak w JSON masz wpisać 10 literek AlaMakota, to przesuwasz wiele wiele więcej, jak zaczynasz, nie wiesz jak długi będzie. W językach z GC po prostu nie wierzę, ze wszędzie się odbywa z oszczędnością alokatora - za dużo w api języka string vs / za mało stringbuilder / bytebuffer. Nie miałem zarzutów, więc nie musiałem grzebać, ale trochę zerkałem w generowany kod do Apache Thrifta. Brzydki, jak najczęściej automaty, ale perfekcyjnie skuteczny, z bardzo małym obciążeniem GC, kopiowania itd. Taka np JVM nie boi się CPU, to zostanie zoptymalizowane, ale GC to problem.

Że jawnie nie transmitujesz liczb, nie myśl w bebechach ich nie ma (długości / daty / godziny / milisekundy do headerów), jest i to sporo. Z 32/64 bitów datetime, którego nigdy nie trzeba będzie parsować, mamy 40 znaków. Parsery zaweraja ify na date microsoftu, formatery na pół wszechświata.
To, co jedna warstwa rozrzutnie pojedzie tekstem, inna będzie ściskać do GZIP-a. Za darmo ?

Parsowanie ... koszt że ho ho w CPU, ilosci obiektów GC i suma RAM
Przy deserializacji złożonych obiektów musisz robić decyzje co do typów, w wydajnym automatycznym kodzie to już jest załatwione

Tuż przez stringiem mam (chyba) licznik, z góry wiesz jak alokować, nie musisz mieć algorytmów "zacznijmy od 16B, jak się nie zmieści to podwoimy". Pewnie jeszcze Unikod, zrobienie ładne (generyczne biblioteki wysokiego poziomu) vs brutalne w jednej warstwie

Nie, nie jestem specjalistą, ale używałem tego (=Apache Thrift, gRPC był analizowany ) kilka razy, wypowiadam się jako zadowolony użytkownik biblioteki. Może bliżej 2023 bym przesunął wygrywającego analizę na gRPC, ale to ta sama liga.

2

gRPC nie jest koniecznie szybsze od zwykłego HTTP API. Jedyne zalety jakie mi przychodzą do głowy to domyślne użycie protobufów, które są mniejsze i szybsze od JSONa a od XMLa to już przepaść (co nie zmienia faktu, że mogę sobie ich używać w HTTP API) oraz fakt użycia HTTP2 co daje minimalne zalety takie jak możliwość użycia jednego fizycznego połączenia przez różne akcje jednocześnie albo binarny header wiadomości, który jest łatwiejszy do sparsowania (ale te zalety są raczej nikłe w przypadku połączeń serwer <-> serwer w jednym data center, co jest chyba najczęstrzym przypadkiem w przypadku gRPC)

gRPC nie jest szybki dlatego, że jest jakoś wspaniale napisany/zaprojektowany tylko dlatego, że cała reszta jest gówniana. Frameworki i biblioteki często są wolne i używają wolnego kodu (opartego o refleksje) do parsowania JSONów.

W gRPC dane przesyłane są binarnie, ale jeśli przesyłamy głównie tekst to chyba nie powinno mieć to wpływu na wydajność a wręcz przeciwnie - tekst musimy zamienić na bity/byte'y - więc będzie dodatkowy narzut, czy może się mylę?

Jeden długi string będzie się raczej parsował tak samo szybko w przypadku protobufów jak i JSONa. W JSONie będzie wolniej, bo jeszcze trzeba sprawdzić, czy nie ma gdzieś w środku znaku wyescapowanego znaku \" a jak jest to trzeba go zamienić na ". To na czym zyskuje protobuf to dużo mniejszy rozmiar danych (bo klucze nie są stringami tylko liczbami, w przypadku tablic złożonych obiektów to może być ogromna część wiadomości) i łatwiejsze, binarne enkodowanie, które nie wymaga parsera dla gramatyki bezkontekstowej.

2

Protobuf/gRPC nie musi w ogóle parsować stringów, po prostu zapisuje długość stringa najpierw i dzięki temu wie ile bajtów ma skopiować ze strumienia. Parser Json natomiast musi patrzeć na każdy znak czy nie jest już koniec stringa.

2

Jeden z tych obszarów, gdzie sie cofamy.

"od zawsze" wiedzieliśmy jaka jest specyfika formatów znakowych i binarnych, każdy junior (wtedy nie uzywalo się tego słowa) umiał dać charakterystykę, a tu nagle w 2023 wiekopomne odkrycie, że się różnią ...

Tak na marginesie, ciekawe czy apostołowie REST/JSON kiedykolwiek zainteresowali się, jak fajnie te nowoczesne prokoły binarne adaptują się do aktualizacji / rozwoju protokołu (podbijania jego wersji). Założę się, że obowiązuje religijna wiara "binarne to od diabła pochodzi"

1 użytkowników online, w tym zalogowanych: 0, gości: 1