Często słyszałem twierdzenie, że języki z dynamicznym pisaniem są bardziej wydajne niż języki z pisaniem statycznym. Jakie są przyczyny tego roszczenia? Czy to nie tylko oprzyrządowanie z nowoczesnymi koncepcjami, takimi jak konwencja nad konfiguracją, wykorzystanie programowania funkcjonalnego, zaawansowane modele programowania i spójne abstrakty? Wprawdzie jest mniej bałaganu, ponieważ (na przykład w Javie) często nie są potrzebne redundantne deklaracje typu, ale można również pominąć większość deklaracji typów w językach o typie statycznym, które używają wnioskowania o typie, nie tracąc innych zalet pisania statycznego. Wszystko to jest również dostępne dla współczesnych języków o typie statycznym, takich jak Scala.
A więc: co można powiedzieć o wydajności z dynamicznym pisaniem, która naprawdę jest zaletą samego modelu pisma?
Wyjaśnienie: Bardziej interesują mnie duże / średnie projekty niż szybkie hacki. :-)
źródło
Odpowiedzi:
Myślę, że to dość bliskie połączenie. Zarówno pisanie dynamiczne, jak i pisanie statyczne mają swoje zalety.
Powody, dla których dynamiczne pisanie jest bardziej wydajne:
Powody, dla których pisanie statyczne jest bardziej wydajne:
Średnio doszedłem do wniosku (po wielu latach doświadczenia po obu stronach ogrodzenia), że dynamiczne pisanie na klawiaturze może być bardziej produktywne w krótkim okresie, ale ostatecznie staje się trudne do utrzymania, chyba że masz bardzo dobre zestawy testów i dyscyplinę testowania.
Z drugiej strony faktycznie wolę podejścia typowane statycznie, ponieważ uważam, że korzyści z poprawności i obsługa narzędzi zapewniają lepszą wydajność w dłuższej perspektywie.
źródło
Dzięki dynamicznym językom możesz pisać kiepski kod szybciej niż podczas używania języka pisanego na maszynie.
Po szybkim utworzeniu ogromnej kupy dynamicznych rzeczy możesz bezpiecznie przejść do innego projektu bez konieczności dbania o długoterminową konserwację.
To wzrost wydajności :)
Żartuję, ale po zaangażowaniu się w projekt wykorzystujący „dynamiczny język” przestraszyłem się ilością niepotrzebnych testów, dokumentacji i konwencji, z którymi musisz sobie poradzić, jeśli chcesz mieć działający produkt.
I z radością wielu błędów w czasie wykonywania, które mogły zostać wykryte podczas kompilacji.
Och, zapomniałem też o tych wszystkich hackach i voodoach, które metaprogramowanie pozwala wam wprowadzić w kodzie!
Tak więc wzrost wydajności może być mitem dla średnich / dużych projektów w całym okresie jego eksploatacji.
źródło
Istnieje również teoretyczny pogląd na ten problem: statyczny system typów jest zasadniczo wyspecjalizowanym prover twierdzeniem, który akceptuje program tylko wtedy, gdy może udowodnić jego poprawność typu. Wszystkie systemy typu statycznego odrzucają niektóre prawidłowe programy, ponieważ żaden rozstrzygalny system typu statycznego nie jest wystarczająco silny, aby udowodnić wszystkie możliwe programy z poprawnym typem.
Można argumentować, że programy, których nie można sprawdzić za pomocą statycznego sprawdzania typów, są hackami i / lub złym stylem, ale jeśli masz już prawidłowy program, a sprawdzanie typów go nie akceptuje, z pewnością ma to negatywny wpływ na produktywność w krótkim okresie.
Niektóre przypadki, w których można zauważyć, że blokator typów przeszkadza, to z ogólnymi kontenerami i ko / kontrawariancją w argumentach i typach zwracanych.
źródło
Jedną z zalet, którą znalazłem w przypadku najbardziej dynamicznych języków, jest to, że ułatwiają pisanie bardziej ogólnego kodu. O wiele łatwiej jest pisać na wyższym poziomie abstrakcji, gdy nie trzeba walczyć z systemem typów, aby to zrobić.
Nie musisz o tym tyle myśleć - pisanie kodu, który robi coś nietrywialnego z dowolnym obiektem w Javie, jest trudne i prawdopodobnie wymaga refleksji, która jest zasadniczo dynamicznie typowana; z czymś takim jak JavaScript, pisanie funkcji, która robi coś interesującego dla wszystkich obiektów, jest drugą naturą. Doskonałym przykładem może być funkcja, którą niedawno napisałem, która pobiera obiekt i zastępuje wszystkie jego metody metodami, które robią to samo, ale także uruchamiają zdarzenie. Nie mam pojęcia, jak podejść do czegoś takiego w Javie. Jednak nie jestem pewien, ile z tego wynika z systemów typów, a ile z innych różnic językowych.
Jednak ostatnio zacząłem używać Haskell. Haskell pozwala mi pisać abstrakcyjny, ogólny kod tak łatwo, jak każdy dynamicznie pisany język, którego użyłem. Mój powyższy przykład Java / JavaScript nie ma sensu w Haskell, ponieważ nie ma obiektów, metod, zdarzeń ani nawet wielu mutacji, ale inne rodzaje ogólnego kodu są naprawdę łatwe do napisania.
W rzeczywistości Haskell może napisać ogólny kod, którego nie potrafią dynamicznie pisane języki; doskonałym przykładem jest
read
funkcja, która jest w zasadzie przeciwieństwemtoString
. Można dostaćInt
lubDouble
czy cokolwiek typ chcesz (tak długo, jak to jest w pewnej klasy typu). Można nawet mieć polimorficzne stałe , więcmaxBound
może być maksymalnaInt
,Double
,Char
... itd., Wszystko w zależności od tego, jakiego typu to ma być.Moja teoria jest teraz taka, że wzrost wydajności dzięki zastosowaniu dynamicznego języka jest zawsze w porównaniu do języków takich jak Java z mniej wydajnymi, bardziej szczegółowymi i mniej elastycznymi systemami typów.
Jednak nawet system pisma Haskell ma pewne irytujące problemy, których nie miałbyś w dynamicznie pisanym języku. Najbardziej denerwuje mnie sposób, w jaki obsługiwane są liczby; na przykład, musisz zadzierać z systemem typów, aby używać
length
(z listy) podwójnie, z czym bez problemów nie miałbyś problemów. Kolejną irytującą rzeczą, na którą się natknąłem, jest praca zWord8
(typu int bez znaku) i funkcje, które oczekująInt
.Tak więc ostatecznie brak systemu typów ułatwia pisanie kodu ogólnego bez zbytniego zastanawiania się, a także pozwala uniknąć irytujących pułapek systemów typu. Nigdy nie musisz walczyć z systemem czcionek w dynamicznym języku, ale nie możesz na nim polegać.
źródło
Int
zwrotu przez listę jest banalne; przykład:1.0 + fromIntegral (length myList)
tj. po prostu użyjfromIntegral
.P: Często słyszałem twierdzenie, że języki z dynamicznym pisaniem są bardziej wydajne niż języki z statycznym pisaniem. Jakie są przyczyny tego roszczenia? „
Ma to przyczyny historyczne. Jeśli cofniesz się o kilka dekad, języki dynamiczne były bezsprzecznie znacznie wydajniejsze niż języki statyczne (choć znacznie wolniejsze). Perl jest wyraźnie bardziej produktywny niż C, jeśli znasz oba i jedno z zadań na to pozwala. Jednak z biegiem czasu wiele języków zapożyczało się od siebie, a nowsze języki zmniejszają lukę (zarówno pod względem wydajności, jak i wydajności).
Oto kilka punktów do rozważenia:
Śmieci : Śmieci to ogromny wzrost wydajności. Wierzę, że Java była pierwszym głównym językiem statycznym z GC. Wcześniej statyczne oznaczało w zasadzie ręczne zarządzanie pamięcią. (Uwaga: tutaj i poniżej rozważam tylko języki głównego nurtu. Istnieje wiele języków eksperymentalnych i niszowych, które zapewnią kontrprzykłady w każdym punkcie, który podniosę.)
Bezpieczeństwo pamięci : Jest to poprawa wydajności, dzięki której nie musisz się martwić o strzelanie sobie w stopę. Przed „zarządzanymi” językami statycznymi, takimi jak Java, statyczny zwykle oznaczał bezpośredni dostęp do pamięci. Debugowanie jest również częścią wydajności, a niebezpieczny dostęp do pamięci może prowadzić do naprawdę niejasnych błędów.
Uciążliwe systemy typu. Przed wprowadzeniem sparametryzowanych typów (takich jak szablony lub generyczne) w językach statycznych ograniczenia systemów typów statycznych często stanowiły obciążenie. Na przykład w Javie trzeba było jawnie spuszczać za każdym razem, gdy wybierasz element z kolekcji. Masz syntaktyczny narzut obsady i nie masz żadnego bezpieczeństwa. Biorąc pod uwagę, jak wszechobecne są kolekcje w programowaniu, była to poważna wada.
Konieczność zadeklarowania rodzaju wszystkiego jest zbyteczna, ale przy nowoczesnym wnioskowaniu można to znacznie zmniejszyć.
Duża standardowa biblioteka. Python był reklamowany jako „dołączone baterie” ze względu na dużą standardową bibliotekę. To w porównaniu z C, które mają bardzo minimalistyczną standardową bibliotekę. Jednak w przypadku platform takich jak Java i .net ogromna standardowa biblioteka staje się standardem, a nowsze języki, takie jak Scala i F #, dziedziczą to „za darmo”.
Struktury danych pierwszej klasy. Dynamiczne języki, takie jak Perl i Python, mają wbudowane pierwszorzędne struktury danych, takie jak listy i mapy, z wygodnymi skrótami składniowymi do typowych operacji. W porównaniu z tym C nie ma wbudowanych kolekcji oprócz tablic o stałym rozmiarze.
Zamknięcia i składnia lambda - języki dynamiczne zwykle miały to od samego początku, ale języki statyczne przyjęły to, ostatnio Java.
REPL umiejętność szybkiego testowania fragmentów kodu interaktywnie jest ogromnym dobrodziejstwem. Ale chociaż narzędzia IDE, takie jak „bezpośrednie” okno w Visual Studio, języki statyczne mogą do pewnego stopnia to emulować.
Zaawansowane oprzyrządowanie - oprócz powyższych punktów, w których języki statyczne zbliżają się do wygody języków dynamicznych, nowi redaktorzy korzystają z analizy statycznej w taki sposób, że języki dynamiczne mają trudności z dopasowaniem. Na przykład redaktorzy mogą zapewnić bezpieczne automatyczne refaktoryzacje, co jest ściśle mówiąc niemożliwe w dynamicznym języku.
Konkluzja: Historycznie to była prawda, ale dziś odpowiedź jest mniej jednoznaczna.
P: Więc: co można powiedzieć o wydajności z dynamicznym pisaniem, która naprawdę jest zaletą samego modelu pisma?
Nieco trudno jest oddzielić dynamiczny model pisania od dynamicznych języków, ale na przykład C # przyjęło bardziej dynamiczne funkcje z czasem, mimo że jego rdzeniem jest język statyczny. To naprawdę dowód na korzyść modelu typu dynamicznego. Przykłady:
Odbicie Odbicie jest zasadniczo funkcją dynamicznego pisania. Rodzaje obiektów są sprawdzane w środowisku wykonawczym niż czas kompilacji. Kiedy został wprowadzony, było to trochę zaniepokojone, ale w C # użycie odbicia staje się coraz bardziej wszechobecne, na przykład ASP.Net MVC mocno wykorzystuje odbicie.
Atrybuty Atrybuty są przykładem dynamicznego pisania. Możesz dodać dowolne atrybuty do klasy w czasie kompilacji, a następnie sprawdzać w czasie wykonywania (poprzez odbicie) i manipulować obiektami na jej podstawie. Coś w rodzaju MEP to w zasadzie struktura rozszerzenia oparta na modelu typu dynamicznego.
Linq do SQL, EF mv. Różne transformatory Linq sprawdzają zapytania jako obiekty wykonawcze i generują sql w locie. Nie robi się bardziej dynamiczny niż sprawdzanie kodu w czasie wykonywania. CodeDom to druga strona medalu, w której kod może być generowany w czasie wykonywania
Roslyn Roslyn w zasadzie implementuje
eval
, co kiedyś uważano za cechę definiującą naprawdę dynamiczny język.Dynamiczny Typ
dynamic
jest najbardziej dynamiczną funkcją w języku C # i jest reklamowany w celu uproszczenia i zwiększenia wydajności interakcji z obiektami zewnętrznymi i językami. Ale dla wygody jest również używany w Asp.net MVC.Zaleta wszystkich powyższych funkcji pokazuje, że model dynamiczny ma określone zalety nawet w języku statycznym z typami sparametryzowanymi, typami strukturalnymi i wnioskowaniem typu.
źródło
Wszystkie nowoczesne funkcje językowe są tak duże, że pisanie statyczne vs. dynamiczne nie ma większego znaczenia.
Zasadą jest, że im lepsze funkcje językowe, tym krótszy kod. To całkiem proste. Java pokazuje, jak pisanie statyczne może się nie udać, co daje przeciwnikom wiele do jedzenia. Źle zaprojektowane funkcje językowe generalnie wiążą się z pewnymi kosztami, a statyczne pisanie w Javie jest po pierwsze obowiązkową funkcją (w przeciwnym razie większość osób prawdopodobnie nawet by jej nie użyła), a po drugie źle wykonane.
Właśnie dlatego w porównaniu świecą najbardziej dynamiczne języki, chociaż twierdzę, że PHP tak naprawdę nie poprawia twojego życia w ogóle (przynajmniej do niedawna), z powodu wielu innych dziwactw niezwiązanych z systemami typów.
Z drugiej strony masz wiele języków z ekspresyjnymi systemami typowania, które nie przeszkadzają i nawet nie są obowiązkowe. Niektóre z nich pozwalają nawet na osadzanie kodu bez typu, gdy tylko trzeba uciec z systemu typów.
Osobiście używam haXe, który jest językiem z wnioskowaniem typu, zarówno podtypem nominalnym, jak i strukturalnym, opcjonalnym nietypowym kodem, typami funkcji pierwszej klasy, algebraicznymi typami danych i (niezbyt dojrzałymi, ale niezwykle potężnymi) makrami leksykalnymi, unikając przy tym tajemnej składni. Po około 3 latach używania haXe doszedłem do prostego wniosku:
Programowanie staje się znacznie łatwiejsze, gdy twój język nie blokuje cię w religijnych wyborach dotyczących paradygmatów, ale stara się być po prostu dobrym narzędziem. Istnieje wiele języków statycznych i dynamicznych oraz języków mieszanych , które odniosły sukces. Niektóre z nich są łatwe do nauczenia, a najtrudniejsze do opanowania.
Ich moc wynika ze sposobu, w jaki poszczególne funkcje można komponować, aby łatwo tworzyć proste rozwiązania skomplikowanych problemów. Wyklucza to pewną ortogonalność, którą można osiągnąć jedynie poprzez delikatną równowagę włączenia lub pominięcia wszystkich zbadanych do tej pory cech językowych. Jeśli spróbujesz dodać statyczne pisanie do Ruby, okaleczysz go, jeśli spróbujesz zabrać go Haskellowi, zmiażdżysz go. W przeciwieństwie do tego: jeśli zabierzesz go z C, ludzie prawie tego nie zauważą, a jeśli zabierzesz go z Javy, niektórzy mogą ci podziękować.
Z własnego doświadczenia mogę ci powiedzieć: lubię Ruby. Poszerzyło to moje horyzonty i sposób projektowania systemów. IMHO powinno się przede wszystkim uczyć programowania ludzi. Jest dyskretny, mocny, zwięzły, zabawny. Rozumiem, dlaczego spodoba się komuś, kto pochodzi z języka ortodoksyjnego.
Na dłuższą metę jednak pisanie statyczne pozwala odroczyć pracę analizatorowi statycznemu, a przy wnioskowaniu typu jest to zasadniczo bezpłatne. W rezultacie powstaje kod, który jest łatwiejszy w utrzymaniu i często działa szybciej.
Ale znowu, samo pisanie statyczne nic nie da. To kwestia połączenia. Myślę, że gdzieś pomiędzy F #, Scala, Nemerle, OCaml lub haXe możesz znaleźć swój własny optymalny. Ale to ostatecznie zależy od ciebie, ponieważ język powinien pozwolić ci na osadzenie myśli bez wysiłku, zamiast zmuszać cię do zginania ich wokół siebie. W końcu nic nie daje większego wzrostu wydajności, niż gdyby programowanie było zabawne.
źródło
Osobiście jedyny powód, dla którego dynamiczne pisanie jest pomocne, to jeśli jesteś naprawdę wolnym maszynistą lub budujesz gigantyczne funkcje / metody / wieloryby, które są trudne w nawigacji. Musisz także przejść do problemu z testowaniem całej jednostki. Typy dynamiczne wymagają (chyba że lubisz pisać zepsuty kod) energicznych testów jednostkowych (Aby upewnić się, że typy dynamiczne nie wybuchają niespodziewanie (tj. Zmienna jest głównie kaczką, ale czasami dcuk przypadkowo)). Statyka będzie starać się o wiele bardziej starać, aby temu zapobiec (i tak, możesz argumentować za energicznymi testami jednostkowymi)
źródło
Myślę, że przede wszystkim musisz zdefiniować „produktywność”. Co oznacza „produktywność” i obejmuje?
Jeśli przez „bardziej produktywny” rozumiesz pisanie mniejszej liczby wierszy kodu w celu zaimplementowania tej samej funkcji, to tak, języki programowania z dynamicznym pisaniem są bardziej „produktywne” niż języki z pisaniem statycznym.
Jeśli jednak weźmiesz również pod uwagę czas poświęcony na debugowanie i naprawianie błędów, języki pisania dynamicznego mogą nie być tak produktywne, ponieważ języki pisania dynamicznego mają tendencję do wypychania sprawdzania błędów do czasu wykonywania, podczas gdy w przeciwieństwie do języków pisania statycznego może wykonać sprawdzanie błędów w czasie kompilacji. Ponieważ powszechnie przyjmuje się, że im później błąd zostanie znaleziony, tym droższe jest jego usunięcie. W związku z tym kodowanie dynamiczne może powodować generalnie taką samą, a może nawet mniejszą produktywność niż kodowanie statyczne.
źródło
Dużą zaletą dynamicznego pisania jest wydajność.
Python, Ruby itp. Oprócz dynamicznego pisania (wiele innych parametrów, słowniki wbudowane w typy itp.) Mają wiele innych programów zwiększających produktywność. Łączny wpływ na produktywność programisty jest imponujący.
Kary pod względem szybkości (lub braku!) I zużycia zasobów nie są tak złe, jak można by się spodziewać, aw większości przypadków rekompensuje je szybkość i elastyczność rozwoju.
Jest na ten temat (bardzo stary!) Artykuł . Jest to jedno z niewielu właściwie przeprowadzonych badań dotyczących wydajności programisty, a wiele wniosków jest nadal aktualnych.
Czym (prawdopodobnie) byłyby inne badania, które zostaną przeprowadzone dzisiaj:
Komunikat brzmi, chyba że wydajność jest naprawdę poważnym problemem. Dynamiczne języki zwiększą produktywność.
źródło