Standardowe kolekcje czy vavr?

0

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ść.

4

ż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.

3

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 na pół, 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.

2

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.

0

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ć.

3
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

2

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 ;]

0
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.

2

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 :)

https://gist.github.com/jboner/2841832

1

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.

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