O wydajności i interoperacyjności Java: Clojure vs. Scala

82

Przeczytałem już różne relacje Clojure vs. Scala i zdaję sobie sprawę, że oba mają swoje miejsce. Jest kilka uwag, których nie uzyskałem pełnego wyjaśnienia, jeśli chodzi o porównanie obu Clojure ze Scalą:

1.) Który z dwóch języków jest generalnie szybszy ? Zdaję sobie sprawę, że będzie się to różnić w zależności od języka, ale ogólna ocena wykonania będzie pomocna. Na przykład: Wiem, że słowniki Pythona są naprawdę szybkie. Ale jako całość jest to znacznie wolniejszy język niż Java. Nie chcę iść z Clojure i napotkać ten problem w przyszłości.

2.) Jak jest współdziałanie z Javą? Wszystko, co do tej pory przeczytałem, to to, że Scala ma natywne typy kolekcji, które sprawiają, że integracja z dużą bazą kodu Java jest nieco niezręczna, podczas gdy Clojure stosuje prosty iterowalny / iteratorowy sposób współdziałania z klasami Java. Masz więcej przemyśleń / szczegółów na ten temat?

Ostatecznie, jeśli jest wystarczająco blisko między clojure i scala, mogę wypróbować oba. Jedną z rzeczy w Clojure jest to, że język wydaje się bardzo prosty. Ale z drugiej strony Scala ma bardzo elastyczny system czcionek. Ale wiem, że Scala jest szybka (w oparciu o wiele kont osobistych). Tak więc, jeśli Clojure jest znacznie wolniejszy: wolałbym wiedzieć wcześniej niż później.

Ryan Delucchi
źródło
1
Z Clojure 1.2 Clojure może wywoływać java bez narzutów. Zajrzyj na assembla.com/wiki/show/clojure/Datatypes and assembla.com/wiki/show/clojure/New_new . Dzieje się tak, ponieważ Clojure chce być blisko Java, ale zaimplementowane w Clojure.
nickik

Odpowiedzi:

73

Myślę, że każdy język będzie dla ciebie wystarczająco szybki. Porównując Python i Javę, obwinianie języka za różnicę w szybkości wydaje się nieco nierozsądne. Java jest kompilowana w JIT (z wyjątkiem urządzeń mobilnych *), podczas gdy Python jest interpretowany. To, że oba używają kodu bajtowego, nie oznacza, że ​​implementacje będą miały nawet zdalnie porównywalną wydajność. Ale zarówno Scala, jak i Clojure są językami JVM, więc powinny mieć podobną wydajność.

Scala ma kilka zalet implementacyjnych w porównaniu z Clojure i spodziewałbym się nieco wyższej wydajności. Chociaż Scala statyczne typowanie zwykle przekładają się na przewagę prędkości nad Clojure jest kaczka wpisywanie, Clojure robi typu wsparcie podpowiedzi, które mogą znacznie przyspieszyć kod. Być może zwykła Scala jest szybsza niż zwykła Clojure, ale wystarczy zoptymalizować wąskie gardła. Większość czasu wykonywania programu jest generowana przez niewielką część rzeczywistego kodu.

Jeśli chodzi o interop w / Java, Scala jest bliższa Javie, ale jestem pewien, że oba języki dobrze ze sobą współdziałają. W Programming Clojure Stuart Halloway pisze: „[można uzyskać dostęp] do wszystkiego, co można uzyskać z kodu Java. ”.

A ponieważ autor Scali, Martin Odersky, napisał kompilator Javy firmy Sun, wydaje mi się, że po stronie Scali nie spadły też żadne piłki. :-)

Trudno byłoby wybrać dwa lepsze języki, chociaż lubię też Ruby. Dlaczego martwisz się, który z nich spróbować? Dlaczego nie wypróbować obu? Scala ma większe szanse być „następną Javą”, chociaż trudno sobie wyobrazić, że Lisp w końcu wystartuje po tym, jak nie robił tego przez ponad 50 lat. Ale jasne jest, że Lisp jest na swoim własnym, unikalnym poziomie abstrakcji, a Clojure jest dość prosty, więc Scala + Clojure nie będzie o wiele trudniejszy niż zwykła (raczej złożona) Scala i jestem pewien, że będziesz zadowolony, że to zrobiłeś to.

A jeśli o to chodzi, współpracują ...

* dalvik (JVM dla Androida) otrzymał kompilator JIT w wersji 2.2 w 2010

DigitalRoss
źródło
6
Huh. Cóż, dzięki za wszystkie spostrzeżenia. Na początku byłem w trybie, w którym chciałem po prostu wybrać jedną i biec z nią. Ale z jakiegoś powodu nie przyszło mi do głowy, że mogę po prostu użyć obu i sprawić, by współdziałały. Więc może wybiorę oba i zrobię z nimi szybki spacer :-)
Ryan Delucchi
7
I dodam, że mam trochę „słabości” do LISP-a, więc fakt, że Clojure cierpi na paretezy, nie wystarczy, żeby mnie odstraszyć.
Ryan Delucchi
8
Nie zawsze jest prawdą, że język napisany w JVM będzie działał z maksymalną prędkością. Oryginalny JRuby miał fatalną wydajność, ponieważ był to interpreter skompilowany do JVM, a nie kod źródłowy. Język również może być winny. Języki z typami statycznymi są często łatwiejsze do optymalizacji niż języki dynamiczne itp.
Bill K
7
-1 „zarówno Scala, jak i Clojure są językami JVM, więc powinny mieć podobną wydajność” nie ma żadnego sensu. Dynamiczne języki, które muszą pozostać interoperacyjne ze statycznymi językami, takimi jak Java, są zawsze znacznie wolniejsze (przeładowanie wiąże się z ogromnymi kosztami, podpowiedzi typu nie rozwiązują wszystkich problemów itp.)
julx
4
@julkiewicz - to po prostu nieprawda, że ​​języki dynamiczne są zawsze dużo wolniejsze. Zależy to od tego, czy Twój kompilator poradzi sobie dobrze z optymalizacją danego kodu. Na przykład w Clojure możesz wykonywać działania arytmetyczne z prymitywami Java, które dokładnie odpowiadają wydajności Java. Podobnie wywołanie metody w obiekcie Java ze wskazówkami do typu jest tak szybkie, jak wywołanie metody obiektu Java. Kompilator Clojure generuje zasadniczo ten sam kod bajtowy, co javac dla równoważnego kodu Java.
mikera
32

W obecnym JVM Scala ma tę zaletę, że jest statycznie wpisywany, ponieważ obsługa JVM dla dynamicznego pisania - odbicie - jest powolna. W rzeczywistości jedna funkcja Scala, która musi być implementowana za pomocą tych samych technik, typów strukturalnych, jest często ostrzegana z tego właśnie powodu.

Ponadto Scala dobrze akceptuje zmienne obiekty, a niektóre algorytmy są po prostu szybsze do zaimplementowania ze zmiennością.

Ponieważ zarówno Scala, jak i Java są zasadniczo językami opartymi na klasach, łatwiej ze sobą współpracują. A może bardziej płynnie. Klasa Javy jest klasą dla Scala, a klasa Scala jest klasą dla Javy. Mogą pojawić się problemy, jeśli chodzi o pojedyncze elementy Scali lub statyczne elementy składowe Javy, szczególnie gdy istnieje framework, który oczekuje, że coś zadziała w określony sposób.

Więc poszedłbym ze Scalą na oba te konta. Clojure jest pod wieloma względami lepszym językiem iz pewnością ma bardzo interesujące funkcje, których (jak dotąd) nie ma w Scali, ale czerpiesz takie korzyści, przechodząc w pełni funkcjonalnie. Jeśli zamierzasz to zrobić, Clojure jest prawdopodobnie lepszym rozwiązaniem. Jeśli tego nie zrobisz, prawdopodobnie powinieneś zostać przy Scali.

Daniel C. Sobral
źródło
9
Funkcjonalne funkcje programowania clojure są najważniejszym powodem, dla którego rozważam ten język. Dochodzę do punktu, w którym: jeśli nie koduję czegoś w sposób funkcjonalny - po co i tak przejmuję się językiem skryptowym osadzonym w Javie? Mam już Pythona po swojej stronie do wykonywania szybkich i trudnych zadań.
Ryan Delucchi
„język skryptowy osadzony w Javie”. Proszę uzasadnić.
Jus12
@Daniel: Przepraszam za zamieszanie. Miałem na myśli komentarz do Ryana Delucchi. Mówi, że Scala to „język skryptowy osadzony w Javie”, którego nie kupuję. (Chyba że miał na myśli Clojure, o którym nie mam pojęcia).
Jus12,
@ Jus12 Uznałem, że oznacza to, że używa tych języków jako języków skryptowych JVM, a biorąc pod uwagę to, nie widzi w nich żadnej przewagi nad Pythonem, chyba że zacznie funkcjonować. Z drugiej strony, nie jestem nim, więc mogę się tylko domyślać.
Daniel C. Sobral,
20

Zauważ, że Clojure i Scala są dwa zupełnie różne rodzaje języków programowania - Clojure jest funkcjonalnym podobny do języka Lisp, to nie obiektowego. Scala to język zorientowany obiektowo, który ma funkcjonalne funkcje programowania.

Moim zdaniem cechy i koncepcje języka (funkcjonalne, OO, ...) są znacznie ważniejszymi kryteriami wyboru języka niż wykonanie (konkretnej implementacji tego języka) - chociaż rozumiem, że nie chcą zostać uwięzieni w języku, dla którego nie ma dostępnej dobrze działającej implementacji.

Wybrałbym Scalę, ponieważ jest zorientowana obiektowo, ale także pozwala nauczyć się programowania funkcjonalnego (jeśli jesteś tym zainteresowany). Z drugiej strony, jeśli nie zależy Ci na OO i chcesz nauczyć się „czystego” programowania funkcjonalnego, wypróbuj Clojure.

Jesper
źródło
9
Najwyraźniej nie używałeś Clojure. Clojure jest tak zorientowany obiektowo, jak Scala jest funkcjonalna. Możesz zaimplementować interfejs, rozszerzyć klasę, zadeklarować funkcje prywatne i statyczne itp. ( Clojure.org/java_interop ).
Richard Clayton,
28
Te rzeczy istnieją w Clojure w celu zapewnienia współdziałania z Javą, ale klasy i obiekty wyraźnie nie są głównymi cechami Clojure. Nie tworzysz klas i nie projektujesz projektu w sposób OO, jeśli zamierzasz programować w Clojure.
Jesper
>> „niż wydajność”. Problem polega na tym, że co się dzieje, gdy - w głębi projektu - odkryjesz, że wydajność jest słaba - a nie tylko z powodu jednego małego fragmentu (który już planowałeś przekonwertować na Java właśnie z tego powodu). Chociaż nie zamierzam tutaj mówić „nie używaj clojure - kropka…”, powinno być jasne, że clojure jest większym ryzykiem na arenie wydajności. Istnieje wiele możliwości tworzenia kodu na poziomie aplikacji, dla których nie ma to znaczenia: ale także wiele baz kodu wykorzystujących framework / wielowątkowość / przetwarzanie, w przypadku których byłoby to obciążeniem.
StephenBoesch
@javadba Pomysł, że clojure jest zły dla niskopoziomowego kodu wielowątkowego, wydaje się dość arbitralny. Clojure jest zaprojektowany w taki sposób, że błędy w programowaniu wielowątkowym są bardzo trudne. Niezmienne dane i funkcje STM, które są rdzeniem języka clojure, są czymś niedostępnym w podstawowej Scali i znacznie zmniejszają prawdopodobieństwo, że programista przypadkowo wstawi stan wyścigu lub zakleszczenie do swojego kodu. Z pewnością jest to cenniejsze niż kilka ms czasu wykonywania, które można uzyskać z języka statycznego, takiego jak Scala lub Java.
nben
„Z pewnością jest to cenniejsze niż kilka ms czasu działania” .. To zależy od skali danych. kilka ms wystarczy dla kilku rekordów. pomnóż przez setki milionów ..
StephenBoesch
16
  1. Idiomatyczne Scala jest szybszy niż idiomatycznym Clojure, i tak pozostanie.
  2. Zarówno Scala, jak i Clojure łatwo współpracują z Javą. Żaden z nich nie siedzi dobrze pod nim.

Jeśli Twój kod jest krytyczny pod względem czasu lub miejsca, trzymaj się Javy. Ale tak nie jest, nawet jeśli myślisz, że tak jest.

Gra Computer Language Benchmark rzuca niewiele światła na rzeczywiste koszty zasobów Clojure. Nie są stosowane żadne struktury danych Clojure. Abstrakcje funkcjonalne i sekwencyjne nie pojawiają się.

Clojure może wydawać się proste. Nie jest, ale jest ekspresyjny. Może działać pięć razy wolniej niż Java, ale źródło jest pięć razy mniejsze (YMMV). W przypadku większości aplikacji jest to duża wygrana. Ale dla niektórych, a dla niektórych części wielu innych, jest to katastrofalna strata.

Wierzę, że mając doświadczenie z językiem Clojure, można z góry stwierdzić, czy problem zostanie wyraźnie podzielony na część, którą można zwięźle i odpowiednio (pod względem wydajności) wyrazić w Clojure oraz część, którą należy wykonać w Javie.

  • Możesz wybrać Scala lite: pisanie idiomów Java w Scali. Zyskasz zwięzłość, łatwiejszą dla oka składnię i spójny, choć złożony system czcionek.
  • Nie ma czegoś takiego jak Clojure lite: pisanie idiomów Java w Clojure jest całkowicie bezcelowe. Wszystko, co otrzymasz, to powolna Java, która jest trudna do zrozumienia, ponieważ wykracza poza ziarno idiomów używanych do jej wyrażenia.

Mówi się, że Scala to dobrze zrobiona Java . Clojure w niczym nie przypomina Java. Można powiedzieć, że to dobrze zrobiony Lisp - śmiałe, niektórzy powiedzieliby niedorzeczne twierdzenie - które może się okazać prawdą.

Miniaturka
źródło
4
Ta odpowiedź rzuca dobre światło na prawdziwe różnice i mocne / słabe strony tych dwóch. Nie jest napisane ani w sposób skalalno-clojure-apologeta, ale raczej w sposób zgodny z prawdą.
StephenBoesch
15

Statystyki generowane przez „ Computer Language Benchmark Game ” są najlepszymi, jakie prawdopodobnie znajdziesz.

Są dogłębne i możesz porównać wiele języków. Problem w tym, że nie obejmują Clojure :(

To powiedziawszy, dość łatwo jest przesłać cokolwiek - wszystko to jest open source.

Statystyki mówią, że Scala jest cholernie szybka.

Bill K.
źródło
9
Proszę bardzo. 2-25x wolniej niż Java, 2-30x więcej pamięci i rozmiar kodu jest generalnie większy niż Java. Wygląda na to, że jest porównywalny z Pythonem, w którym Scala jest bardzo zbliżona do Javy. Powiedziałbym, że Scala jest całkiem wyraźnym zwycięzcą, a Clojure jest znacznie wolniejszy - chyba że test Clojure był słabo napisany.
Bill K
2
Wygląda na to, że benchmark obejmuje teraz Clojure (uwaga OP ma rok). Wyniki nie są zachęcające. Scala to droga do zrobienia.
Martin
4
Powyższe komentarze są nieco nieaktualne - od połowy 2012 r. Clojure znacznie zmniejszył lukę, teraz średnio tylko około 2x Java.
mikera
9

Jeśli chodzi o interoperacyjność, nie mogę mówić w imieniu Clojure, ale spodziewałbym się, że będzie w podobnej sytuacji jak Scala.

Wywołanie Java ze Scali jest banalnie proste.

Wywołanie Scali z języka Java jest łatwe, o ile dostosujesz zewnętrzny interfejs API do punktów wspólnych między Scalą i Javą. Na przykład obiekt Scala jest używany w pewien sposób, podobnie jak metody statyczne w Javie, ale to nie to samo. Klasy Scala można skompilować do wielu klas, których nazwy wyglądają śmiesznie w Javie.

Nie będziesz chciał wiele mieszać i dopasowywać. Tworzenie komponentu w Scali lub Clojure, który używa wielu bibliotek Java, jest bardzo wykonalne. Możesz oczywiście wywołać ten komponent z Javy, ale nie będziesz chciał korzystać z API Scala przeznaczonego do użycia przez programy Scala z Javy.

SVN twierdzi, że jest „dobrze zrobione CVS”. Moim zdaniem Scala to dobrze zrobiona Java.

Kevin Peterson
źródło
1
@Ron haha, myślałem dokładnie to samo.
KoW
2
Właściwie kolekcje Clojure są gitarowe
Joe Lehmann
2

W wydaniu PragPub z listopada 2010 roku omówiono współdziałanie Clojure-Java. Wywoływanie metod Javy jest proste, ale rozszerzanie klas / interfejsów Javy jest zupełnie inne.

Z drugiej strony Scala jest znacznie bliższa Javie. Interoperacyjność Scala-Java jest opisana pod adresem http://www.codecommit.com/blog/java/interop-between-java-and-scala

Wywoływanie kodu Java i rozszerzanie klas / interfejsów Java działa tak samo, jak wywoływanie kodu Scala. Niektóre problemy mogą być skrajnymi przypadkami radzenia sobie z generycznymi językami Javy, ponieważ system typów w Scali jest znacznie silniejszy niż w Javie. Tworzenie metod pobierających i ustawiających zgodnie z konwencją Java Bean wymaga adnotacji .

Wywołanie Scali z języka Java jest w większości przypadków proste, ale na przykład obiekty towarzyszące Scali wymagają wiedzy, w jaki sposób są kompilowane do kodu bajtowego. Również używanie cech z metodami nieabstrakcyjnymi z Javy powinno być skomplikowane, a wywoływanie metod ze znakami specjalnymi wymagałoby znajomości sposobu ich zakodowania w kodzie bajtowym.

Esko Luontola
źródło
1

Warto teraz (stan na maj 2010) znaleźć najnowszą gałąź 1.2 Clojure - obejmuje to wiele dodatkowej obsługi typów pierwotnych i statycznego pisania (poprzez różne podpowiedzi i protokoły typów).

Rozumiem, że możesz użyć tych funkcji, gdy potrzebujesz ich, aby uzyskać szybkość odpowiadającą pisaniu dokładnie tego samego kodu w czystej Javie.

mikera
źródło
2
Jednocześnie @specializedtechnika w nadchodzącej Scali 2.8 wnosi analogiczne ulepszenia do bibliotek Scala. Jako narzędzie językowe jest dostępne dla całego kodu, nie tylko dla biblioteki standardowej.
Randall Schulz