Wysoka wydajność serializacji: Java vs Google Protocol Buffers vs ...?
Jeśli chodzi o buforowanie, które zastanawiam się nad zrobieniem dla nadchodzącego projektu, myślałem o serializacji w Javie. A mianowicie, czy należy go używać?
Teraz wcześniej pisałem niestandardową serializację i deserializację (zewnętrznie) z różnych powodów w przeszłości. W dzisiejszych czasach interoperacyjność stała się jeszcze większym problemem i mogę przewidzieć potrzebę interakcji z aplikacjami.Net, więc pomyślałem o użyciu rozwiązania niezależnego od platformy.
Czy ktoś miał jakieś doświadczenie z wykorzystaniem GPB o wysokiej wydajności? Jak wypada w porównaniu pod względem szybkości i wydajności z natywną serializacją Javy? Alternatywnie, czy są jakieś inne programy warte rozważenia?
7 answers
Nie porównałem buforów protokołów z natywną serializacją Javy pod względem szybkości, ale dla interoperacyjności natywna serializacja Javy jest poważnym Nie-Nie. W większości przypadków nie będzie on również tak wydajny pod względem przestrzeni, jak bufory protokołów. Oczywiście jest nieco bardziej elastyczny pod względem tego, co może przechowywać, a także pod względem referencji itp. Bufory protokołów są bardzo dobre w tym, do czego są przeznaczone, a kiedy pasują do Twoich potrzeb, są świetne - ale są oczywiste ograniczenia ze względu na do interoperacyjności (i innych rzeczy).
Niedawno opublikowałem Framework testowania buforów protokołów w Javie i. NET. Wersja Javy znajduje się w głównym projekcie Google (w katalogu benchmarks), wersja.Net jest w moim projekcie C# port. Jeśli chcesz porównać szybkość PB z szybkością serializacji Javy, możesz napisać podobne klasy i je porównać. Jeśli jednak interesuje Cię interop, naprawdę nie dałbym natywnej serializacji Javy (lub. NET natywna binarna serializacja) druga myśl.
Oprócz buforów protokołów istnieją inne opcje interoperacyjnej serializacji - Thrift, JSON i YAML przychodzą na myśl i są niewątpliwie inni.
EDIT: ok, ponieważ interop nie jest tak ważny, warto spróbować wymienić różne cechy, które chcesz z RAM serializacji. Jedną z rzeczy, o których warto pomyśleć, jest wersjonowanie-to kolejna rzecz, do której PB jest przeznaczony dobrze radzisz sobie, zarówno do tyłu, jak i do przodu ( aby nowe oprogramowanie mogło odczytać stare dane i odwrotnie) - oczywiście przy trzymaniu się sugerowanych reguł:) {]}
Starając się być ostrożnym w kwestii wydajności Javy i natywnej serializacji, nie zdziwiłbym się, gdyby PB i tak było szybsze. Jeśli masz taką możliwość, użyj maszyny wirtualnej serwera - moje ostatnie testy wykazały, że maszyna wirtualna serwera jest ponad dwa razy szybsza przy serializacji i deserializacji przykładowych danych. Chyba kod PB bardzo ładnie pasuje do JIT serwera VM:)
Podobnie jak przykładowe dane wydajności, serializując i deserializując dwie wiadomości (jeden 228 bajtów, jeden 84750 bajtów) otrzymałem te wyniki na moim laptopie przy użyciu serwera VM:
Benchmarking benchmarks.GoogleSize$SizeMessage1 with file google_message1.dat Serialize to byte string: 2581851 iterations in 30.16s; 18.613789MB/s Serialize to byte array: 2583547 iterations in 29.842s; 18.824497MB/s Serialize to memory stream: 2210320 iterations in 30.125s; 15.953759MB/s Deserialize from byte string: 3356517 iterations in 30.088s; 24.256632MB/s Deserialize from byte array: 3356517 iterations in 29.958s; 24.361889MB/s Deserialize from memory stream: 2618821 iterations in 29.821s; 19.094952MB/s Benchmarking benchmarks.GoogleSpeed$SpeedMessage1 with file google_message1.dat Serialize to byte string: 17068518 iterations in 29.978s; 123.802124MB/s Serialize to byte array: 17520066 iterations in 30.043s; 126.802376MB/s Serialize to memory stream: 7736665 iterations in 30.076s; 55.93307MB/s Deserialize from byte string: 16123669 iterations in 30.073s; 116.57947MB/s Deserialize from byte array: 16082453 iterations in 30.109s; 116.14243MB/s Deserialize from memory stream: 7496968 iterations in 30.03s; 54.283176MB/s Benchmarking benchmarks.GoogleSize$SizeMessage2 with file google_message2.dat Serialize to byte string: 6266 iterations in 30.034s; 16.826494MB/s Serialize to byte array: 6246 iterations in 30.027s; 16.776697MB/s Serialize to memory stream: 6042 iterations in 29.916s; 16.288969MB/s Deserialize from byte string: 4675 iterations in 29.819s; 12.644595MB/s Deserialize from byte array: 4694 iterations in 30.093s; 12.580387MB/s Deserialize from memory stream: 4544 iterations in 29.579s; 12.389998MB/s Benchmarking benchmarks.GoogleSpeed$SpeedMessage2 with file google_message2.dat Serialize to byte string: 39562 iterations in 30.055s; 106.16416MB/s Serialize to byte array: 39715 iterations in 30.178s; 106.14035MB/s Serialize to memory stream: 34161 iterations in 30.032s; 91.74085MB/s Deserialize from byte string: 36934 iterations in 29.794s; 99.98019MB/s Deserialize from byte array: 37191 iterations in 29.915s; 100.26867MB/s Deserialize from memory stream: 36237 iterations in 29.846s; 97.92251MB/s
"Prędkość" vs "rozmiar" to to, czy wygenerowany kod jest zoptymalizowany pod kątem prędkości czy rozmiaru kodu. (Serializowane dane są takie same w obu przypadkach. Wersja "rozmiar" jest przewidziana dla przypadku, w którym zdefiniowano wiele wiadomości i nie chcesz zabierać dużo pamięci za Kod.)
Jak widzisz, dla mniejszej wiadomości może to być bardzo szybko - ponad 500 małych wiadomości serializowanych lub deserializowanych na milisekundę . Nawet z wiadomością 87K zajmuje mniej niż milisekundę na wiadomość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-05 20:24:27
Jeszcze jeden punkt danych: ten projekt:
Http://code.google.com/p/thrift-protobuf-compare/
Daje pewne wyobrażenie o oczekiwanej wydajności dla małych obiektów, w tym serializacji Javy na PB.
Wyniki różnią się znacznie w zależności od platformy, ale istnieją pewne ogólne trendy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 18:17:53
Jeśli mylisz PB i natywną serializację Javy pod względem szybkości i wydajności, po prostu wybierz PB.
- PB został zaprojektowany, aby osiągnąć takie czynniki. Zobacz http://code.google.com/apis/protocolbuffers/docs/overview.html
- Dane PB są bardzo małe, podczas gdy serializacja Javy ma tendencję do replikowania całego obiektu, w tym jego sygnatury. Dlaczego zawsze dostaję nazwę mojej klasy, nazwę pola... serializowane, mimo że znam to na wylot w odbiorniku?
- Think about across rozwój języka. Jest coraz trudniej, jeśli jedna strona używa Javy, a druga C++...
Niektórzy programiści sugerują Thrift, ale ja użyłbym Google PB, bo "wierzę w google": -).. W każdym razie, warto zajrzeć: http://stuartsierra.com/2008/07/10/thrift-vs-protocol-buffers
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-15 17:25:05
Co masz na myśli przez wysoką wydajność? Jeśli chcesz milisekundowej serializacji, sugeruję skorzystanie z podejścia serializacji, które jest najprostsze. Jeśli chcesz sub milisekund, prawdopodobnie potrzebujesz formatu binarnego. Jeśli potrzebujesz znacznie poniżej 10 mikro-sekund, prawdopodobnie będziesz potrzebować niestandardowej serializacji.
Nie widziałem wielu benchmarków dla serializacji / deserializacji, ale kilka obsługuje mniej niż 200 mikro-sekund dla serializacji / deserializacji.
Platforma niezależna formaty są kosztowne (w wysiłku z twojej strony i opóźnienia) być może będziesz musiał zdecydować, czy chcesz wydajności lub niezależności platformy. Nie ma jednak powodu, dla którego nie można mieć obu opcji konfiguracji, które można przełączać w razie potrzeby.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-15 13:53:26
Możesz również spojrzeć na FST , zamiennik wbudowanej serializacji JDK, która powinna być szybsza i mieć mniejszą wydajność.
Surowe szacunki dotyczące częstych benchmarkingu, które zrobiłem w ostatnich latach:
100% = podejścia oparte na binarnych/struct (np. SBE, FST-structs)
- niewygodne [[9]}postprocessing (budowanie "prawdziwych" obejcts po stronie odbiornika) może pochłonąć zalety wydajności i nigdy nie jest uwzględniany w benchmarki
~10%-35% protobuf & pochodne
~10%-30% szybkie serializery, takie jak FST i KRYO
- wygodne, deserializowane obiekty mogą być używane najczęściej bezpośrednio bez dodatkowego kodu tłumaczenia ręcznego.
- może być pimped dla wydajności (adnotacje, Rejestracja klasy)
- zachowaj linki w grafie obiektu (bez obiektu serializowanego dwa razy)
- może obsługiwać struktury cykliczne
- ogólne rozwiązanie, FST jest w pełni kompatybilny z JDK serializacja
~2%-15% serializacja JDK
~1%-15% szybki JSon (np. Jackson)
- nie może obsługiwać żadnego grafu obiektowego, a jedynie niewielki podzbiór struktur danych Javy
- no ref
0.001-1% full graph JSon / XML (np. JSON.io)
Te liczby mają dać bardzo szorstki obraz rzędu wielkości. Należy pamiętać, że wydajność zależy w dużej mierze od serializowanych/benchmarkowanych struktur danych. So single simple class benchmarks są w większości bezużyteczne (ale popularne: np. ignorowanie unicode, brak kolekcji,..).
Zobacz też
Http://java-is-the-new-c.blogspot.de/2014/12/a-persistent-keyvalue-server-in-40.html
Http://java-is-the-new-c.blogspot.de/2013/10/still-using-externalizable-to-get.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 08:10:08
Oto propozycja dnia off the wall: -) (właśnie podkręciłeś coś w mojej głowie, co teraz chcę wypróbować)...
Jeśli możesz przejść do całego rozwiązania buforowania przez to może działać: Project Darkstar . Został zaprojektowany jako bardzo wydajny serwer gier, specjalnie po to, aby odczyty były szybkie (tak dobre dla pamięci podręcznej). Ma Java i C API więc wierzę (myślałem, że dawno na to nie patrzyłem, a wtedy o tym nie myślałem), że można zapisać obiektów z Javą i odczytać je z powrotem w C i odwrotnie.
Jeśli nic więcej to da ci coś do poczytania dzisiaj: -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-15 15:36:35
W przypadku serializacji przyjaznej przewodowi, rozważ użycie interfejsu zewnetrznego. Sprytnie wykorzystane, będziesz miał intymną wiedzę, aby zdecydować, jak optymalnie marshall i unmarshall konkretnych dziedzinach. To powiedziawszy, będziesz musiał poprawnie zarządzać wersjami każdego obiektu - łatwe do usunięcia, ale ponowne ustawienie obiektu V2, gdy twój kod obsługuje V1, spowoduje złamanie, utratę informacji lub, co gorsza, uszkodzenie danych w sposób, w jaki aplikacje nie są w stanie poprawnie przetworzyć. Jeśli szukasz optymalna ścieżka, uważaj Żadna biblioteka nie rozwiąże Twojego problemu bez kompromisów. Ogólnie biblioteki będą pasować do większości przypadków użycia i będą dostarczane z dodatkową korzyścią, że będą dostosowywać i ulepszać z czasem bez Twojego wkładu, jeśli zdecydowałeś się na aktywny projekt open source. Mogą też dodawać problemy z wydajnością, wprowadzać błędy, a nawet naprawiać błędy, które jeszcze na ciebie nie wpłynęły!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 21:06:39