Czy warto używać kolekcji z vavr zamiast standardowych kolekcji?
Jakie mamy korzyści? Do tej pory używałem tej biblioteki tylko po to
aby mieć Either. Jeżeli chodzi o kolekcje używam standardowych
z Javy. Biorąc pod uwagę, że większość innych bibiotek, których używałem
też wykorzystuje standardowe z javy (lub jakieś swoje) nie widziałem sensu
żeby używać innych i przepakowywać z jednego na drugie co pewnie też
jest jakimś overhead na wydajność.
- Rejestracja:ponad 11 lat
- Ostatnio:2 dni
- Lokalizacja:Gdańsk
- Rejestracja:ponad 4 lata
- Ostatnio:ponad 2 lata
- Lokalizacja:Warszawa
- Postów:1092
żeby używać innych i przepakowywać z jednego na drugie co pewnie też
Narzut związany z kolekcjami VAVR jest dużo mniejszy niż z operacjami IO. Jeżeli używasz jakiegoś hajbernejta to te skopiowanie 3 elementów z ArrayList do jakiegoś Vector czy Array jest pomijalnie mała.
Dodatkowo często możesz zwracać Streamy javove a wtedy robisz po prostu Collectora. A to czy warto używać już zalezy od konkretnego przypadku.

- Rejestracja:ponad 8 lat
- Ostatnio:około 7 godzin
- Lokalizacja:U krasnoludów - pod górą
- Postów:4709
W javie/kotlinie tylko vavr od czasów jak jeszcze nazywał się javaslang.
Przepakowywanie przy korzystaniu z bibliotek się zdarza, ale wcale nie tak często. Wiele bibliotek ma pluginy do vavr (np. jackson, jdbi). Przez co przepisywania albo nie ma wcale, albo przynajmniej nie ma w kodzie :-)
Są dwa i pół głównych powodów:
- błędogenność mutowalnych kolekcji - po kilkutygodniowej pracy z vavr lub scalą każde spotkanie z
java.util
to odkrywanie, że znowu ktoś zrobił buga, którego nie można by zrobić w vavr. (klasyczne mutowalne vs niemutowalne), (*
) - czytelność kodu - strumienie javowe są brzydkie do zarzygania,
- wydajność (to pół) - jeśli pracuje nad większym projektem w javie z użyciem
java.util
to praktycznie wszędzie robię defensywne kopiowanie, za wiele razy się rozczarowałem (getCollection().add(x)
to patent, który ma wielu wyznawców). To oczywiście mocno muli, a szczególnie jak robimy to przez ileś warstw. Z vavr nie ma tego problemu. Ten argument jest tak napół
, bo w praktyce, ze względu na wielkość typowych kolekcji i tak problemu nie ma. Natomiast, to że nie muszę używać defensywnego kopiowania poprawia czytelność (punkt 2).
*
- jest druga strona medalu. Jak się przyzwyczaimy do niemutowalności to każde spotkanie z kodem mutowalnym sprawia, że potykamy się o własne nogi.
- Rejestracja:ponad 12 lat
- Ostatnio:minuta
- Postów:3612
Jeśli chodzi o wydajność - jeśli korzystasz z vavr'a produkcyjnie to na 90% przejście na kolekcje z tej biblioteki będzie niezauważalne dla przeciętnego użytkownika, który pewnie nie zauważy różnicy pomiędzy 300, a 600 milisekund. A straty z powodu użycia tych kolekcji pewnie będą mniejsze.
Dopóki nie poruszasz się w naprawdę ciężkim środowisku, które w dodatku jest trudno skalowalne (przetwarzanie dużych ilości danych w pamięci lub gdy dziesięć milisekund różnicy to dużo) to dywagacje typu "której listy użyć" mają dosyć małe znaczenie.
- Rejestracja:ponad 11 lat
- Ostatnio:2 dni
- Lokalizacja:Gdańsk
będzie niezauważalne dla przeciętnego użytkownika, który pewnie nie zauważy różnicy pomiędzy 300, a 600 milisekund. A straty z powodu użycia tych kolekcji pewnie będą mniejsze.
Ale imo chyba lepiej tworzyć kod jak najbardziej wydajny 10ms tu 20 tam i się zbiera.
A jak jest z wsparciem z frameworkami np. spring, hibernate?
Zakładam, że spring raczej nie będzie umiał mi wstrzyknąć listy vavrower
albo hibernate nie zrobi mi impl vavrowej. W efekcie tak czy siak musimy
obu implementacji używać.

- Rejestracja:ponad 8 lat
- Ostatnio:około 7 godzin
- Lokalizacja:U krasnoludów - pod górą
- Postów:4709
lookacode1 napisał(a):
Ale imo chyba lepiej tworzyć kod jak najbardziej wydajny 10ms tu 20 tam i się zbiera.
Generalnie poprawność kodu jest ważniejsza od wydajności.
W (ponad) 90% procentach kodu wydajność (CPU) w ogóle nie ma żadnego znaczenia.
Gdyby było inaczej to czy pisałbyć w javie, czy raczej w ASM/C (no ewentualnie Rust - jeśli zawężamy się do cywilizowanych rozwiązań).
Co więcej, użycie vavr wcale nie oznacza zmniejszenia wydajności - wręcz przeciwnie, można czasem polepszyć (patrz mój poprzedni post).
Faktem jest, że o ile z użyciem vavr dużo łatwiej jest napisać poprawny kod (niż z java.util
), to jeszcze łatwiej jest też napisać ten kod niewydajny :-/
Jeśli jednak w jakimś fragmencie potrzebna będzie wydajność to w typowym projekcie wystarczy doczytać jak ten vavr działa i jak używać, aby uzyskać sensowną wydajność bez zniżania się do java.util.
Co do magicznych frameworków - proszę: dwa w jednym: https://www.baeldung.com/spring-vavr
- Rejestracja:ponad 4 lata
- Ostatnio:ponad 2 lata
- Lokalizacja:Warszawa
- Postów:1092
Ale imo chyba lepiej tworzyć kod jak najbardziej wydajny 10ms tu 20 tam i się zbiera.
Przedwczesna optymalizacja to jeden z największych błędów. A jak masz w projekcie Vavr i JPA to dla performance zacząłbym od wywalenia JPA ;]
- Rejestracja:ponad 11 lat
- Ostatnio:2 dni
- Lokalizacja:Gdańsk
scibi_92 napisał(a):
Ale imo chyba lepiej tworzyć kod jak najbardziej wydajny 10ms tu 20 tam i się zbiera.
Przedwczesna optymalizacja to jeden z największych błędów. A jak masz w projekcie Vavr i JPA to dla performance zacząłbym od wywalenia JPA ;]
Tak wiem, że JPA daje narzut ale nie pozbędziesz się tego z dnia na dzień w projekcie, który już funkcjonuje na produkcji ;).
A jeżeli chodzi o optymalizacje to myślę, że warto zwracać uwagę na liczbę tworzonych obiektów / kolekcji, im mniej tym lepiej
i też mniej roboty dla GC. Kolejna rzecz to jak wiele osób działa w projekcie to pewnie by było tak, że raz jedni by używali kolekcji
z vavr a inni tych standardowych i by jeszcze gorzej wyszło podobnie jak miałem z testng to używali tego co im pasuje albo junit
albo testng.

- Rejestracja:około 17 lat
- Ostatnio:około 2 godziny
- Postów:1881
A jeżeli chodzi o optymalizacje to myślę, że warto zwracać uwagę na liczbę tworzonych obiektów / kolekcji, im mniej tym lepiej
i też mniej roboty dla GC.
Minor GC to żadna robota dla GC, możesz sobie tworzyć zylion obiektów, o ile nie trzymasz tego w jakiejś sesji. Po drugie 10-20 ms, o ktorych pisaleś wcześniej - to jest rząd wielkości odpytania bazy danych i to niezbyt zoptymalizowanej. Nie warto kombinować z jakimiś optymalizacjami w kodzie, pierwszy lepszy refaktor je zmiecie :)
- Rejestracja:ponad 4 lata
- Ostatnio:ponad 2 lata
- Lokalizacja:Warszawa
- Postów:1092
I tak swoją drogą, to właśnie immutable objety dają częto lepszy performance. Jedna korzyść to brak kopi defensywnych, druga jest taka że z punktu widzenia GC o wiele lepszy jest młody obiekt który wskazuje na stary niz odwrotnie.
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.
A straty z powodu użycia tych kolekcji pewnie będą mniejsze.