Porównuję dwie technologie, aby uzyskać rekomendację, z której firma powinna skorzystać. Kod technologii A jest interpretowany, podczas gdy kod technologii B jest kompilowany do kodu maszynowego. W moim porównaniu stwierdzam, że ogólnie technologia B miałaby lepszą wydajność, ponieważ nie ma dodatkowego obciążenia związanego z procesem interpretacji. Oświadczam również, że ponieważ program można napisać na wiele sposobów, nadal jest możliwe, że program napisany w tech A może przewyższyć program napisany w tech B.
Kiedy przekazałem ten raport do recenzji, recenzent stwierdził, że nie podałem żadnego wyraźnego powodu, dla którego ogólnie koszty interpretacji byłyby na tyle duże, że moglibyśmy dojść do wniosku, że wydajność technologii B byłaby lepsza.
Więc moje pytanie brzmi: czy możemy kiedykolwiek powiedzieć coś o wydajności skompilowanych / interpretowanych technologii? Jeśli możemy powiedzieć, że kompilacja jest generalnie szybsza niż interpretowana, jak mogę przekonać recenzenta o moim punkcie?
Odpowiedzi:
Nie.
Zasadniczo wydajność implementacji języka zależy przede wszystkim od kwoty pieniędzy, zasobów, siły roboczej, badań, inżynierii i rozwoju.
W szczególności wydajność konkretnego programu zależy przede wszystkim od ilości myśli włożonej w jego algorytmy.
Istnieje kilka bardzo szybkich interpretatorów i niektóre kompilatory, które generują bardzo wolny kod.
Na przykład jednym z powodów, dla których Forth jest nadal popularny, jest to, że w wielu przypadkach interpretowany program Forth jest szybszy niż równoważny skompilowany program C, a jednocześnie program użytkownika napisany w Forth plus napisany interpreter Forth w C jest mniejszy niż program użytkownika napisany w C.
źródło
Uogólnienia i konkretne scenariusze są dosłownie przeciwieństwami.
Wydaje się, że sam sobie przeczysz. Z jednej strony chcesz złożyć ogólne oświadczenie o językach interpretowanych a skompilowanych. Ale z drugiej strony chcesz zastosować to ogólne stwierdzenie do konkretnego scenariusza dotyczącego Technologii A i Technologii B.
Gdy zastosujesz coś do konkretnego scenariusza, nie jest to już uogólnione . Więc nawet jeśli potrafisz stwierdzić, że interpretowane języki są ogólnie wolniejsze , nadal nie masz racji. Twój recenzent nie dba o uogólnienia. Robisz analizę dwóch bardzo specyficznych technologii. To dosłownie przeciwieństwo uogólnienia.
źródło
Zasadniczo interpretowany program jest około 2x – 10x wolniejszy niż pisanie programu w języku hosta tłumacza, przy czym tłumacze dla bardziej dynamicznych języków są wolniejsi. Jest tak, ponieważ interpretowany program musi wykonać całą rzeczywistą pracę, ale dodatkowo ma narzut interpretacji.
W zależności od struktury tłumacza mogą występować bardzo znaczące różnice. Istnieją dwie sprzeczne szkoły projektowania interpreterów: jedna mówi, że kody powinny być tak małe, jak to możliwe, aby można je było łatwiej zoptymalizować, a druga mówi, że kody powinny być tak duże, jak to możliwe, abyśmy mogli więcej pracować w tłumaczu. Kiedy struktura twojego programu odpowiada filozofii tłumacza, koszty ogólne stają się nieistotne.
Np. Perl jest interpretowanym językiem ukierunkowanym na manipulację tekstem. Idiomatyczny program Perl wykonujący manipulację tekstem nie będzie dużo wolniejszy niż program C, aw niektórych przypadkach może nawet przewyższyć program C (możliwe, ponieważ Perl używa innej reprezentacji ciągu i ma wbudowane różne optymalizacje związane z tekstem i IO). Jednak robienie liczb w Perlu będzie nieznośnie wolne. Przyrost
++x
jest pojedynczą instrukcją asemblera, ale wymaga wielu przejść wskaźnikowych i rozgałęzień dla interpretera Perla. Niedawno przeniosłem związany z procesorem skrypt Perla do C ++ i uzyskałem przyspieszenie 7x – 20x, w zależności od poziomu optymalizacji kompilatora.Mówienie o optymalizacji jest tutaj ważne, ponieważ dopracowany, zoptymalizowany interpreter może znacznie przewyższyć nieoptymalizujący naiwny kompilator. Ponieważ tworzenie kompilatora optymalizującego jest trudne i wymaga dużego wysiłku, jest mało prawdopodobne, aby Twoja „technologia B” miała taki poziom dojrzałości.
(Uwaga: Witryna gier komputerowych z testami porównawczymi ma mylącą strukturę, ale gdy osiągniesz tabelę czasową jednego problemu, zauważysz, że wydajność różnych języków jest wszędzie - często nie ma wyraźnej granicy wydajności pomiędzy skompilowanymi i interpretowanymi rozwiązaniami. Najważniejszą częścią witryny nie są wyniki testów porównawczych, ale dyskusje na temat tego, jak trudne są znaczące testy porównawcze).
Przy wyborze technologii samo wykonanie środowiska uruchomieniowego języka jest całkowicie nieistotne. Bardziej prawdopodobne jest, aby technologia spełniała pewne podstawowe ograniczenia (nasz budżet wynosi x USD, musimy być w stanie dostarczyć przed rrrr-mm-dd, musimy spełnić różne niefunkcjonalne wymagania) i że ma ona niższy poziom całkowity koszt posiadania (uwzględnienie wydajności programisty, kosztów sprzętu, kosztów okazji biznesowych, ryzyka błędów i nieoczekiwanych ograniczeń w technologii, kosztów utrzymania, kosztów szkolenia i zatrudnienia, ...). Np. W branży, w której najważniejszy jest czas wprowadzenia produktu na rynek, najlepiej pasowałaby technologia o najlepszej wydajności programistów. W przypadku dużej organizacji łatwość utrzymania i koszty długoterminowe mogą być bardziej interesujące.
źródło
Absolutnie możesz powiedzieć coś o wydajności skompilowanych / interpretowanych technologii. Ale najpierw musisz zdefiniować „wydajność”. Jeśli budujesz prosty pod względem obliczeniowym system wbudowany, wówczas „wydajność” prawdopodobnie skłania się ku stronie wykorzystania pamięci. Podczas gdy złożony obliczeniowo system działający na dużych zestawach danych sam zdefiniowałby „wydajność” w liczbie obliczeń na jednostkę czasu, ponieważ narzut pamięci z JVM lub .NET byłby znikomy.
Gdy zdecydujesz, co to jest „wydajność”, możesz powiedzieć coś w rodzaju „będziemy mieć w dowolnym momencie 50 miliardów obiektów w pamięci, a zinterpretowana technologia doda do każdego obiektu dodatkowe 8 bajtów na potrzeby zarządzania wewnętrznego, co odpowiada nakładowi pamięci 400 GB w porównaniu do techB, który nie dodaje tych danych ”
źródło
To pytanie techniczne i masz już wiele dobrych odpowiedzi technicznych, ale chciałbym zwrócić uwagę na nieco inny aspekt twojej sytuacji: fakt, że nie możesz po prostu podjąć decyzji w rodzaju „technologii A lub technologii B” wyłącznie z przyczyn technicznych i / lub wydajnościowych.
Techniczne aspekty czegoś takiego to tylko niewielka część decyzji między A i B. Należy pamiętać o dziesiątkach innych czynników:
Jak widać, przy podejmowaniu takiej decyzji należy rozważyć MASĘ rzeczy.
Wiem, że to nie odpowiada konkretnie na twoje pytanie, ale myślę, że daje to większy obraz twojej sytuacji i specyfiki takiej decyzji.
źródło
Częściowa ocena to ramy koncepcyjne odpowiednie do powiązania tłumaczy ustnych i kompilatorów.
Językami programowania są specyfikacje (napisane w niektórych raportach, takich jak R5RS lub n1570 ). Są nie oprogramowanie, więc nie ma sensu mówić o wydajności . Ale niektóre języki programowania mogą mieć kilka implementacji, w tym tłumaczy i kompilatorów .
Nawet w tradycyjnie skompilowanych językach (tj. Językach, których implementacje są często kompilatorami), takich jak C, niektóre części są często interpretowane. Na przykład ciąg kontrola formatu printf (zdefiniowane w standardzie C) jest często „interpretować” (przez C standardowej biblioteki , która posiada
printf
funkcję przy użyciu zmiennych argumentów technik), ale niektóre kompilatory (w tym GCC ) są w stanie -w ograniczoną specyficznego przypadki - w celu optymalizacji i „skompilowania” go w wywołania niższego poziomu.Niektóre implementacje, nawet w „interpreterach”, wykorzystują techniki kompilacji JIT (więc generuj kod maszynowy w czasie wykonywania ). Dobrym przykładem jest luajit . Inne implementacje (np. Python, Ocaml, Java, Parrot, Lua) tłumaczą kod źródłowy na kod bajtowy, który jest następnie interpretowany.
SBCL to „kompilator” Common Lisp, który dynamicznie tłumaczy każdą interakcję REPL (i wywołania
eval
itp.) Na kod maszynowy. Więc czujesz, że to tłumacz. Większość implementacji JavaScript w przeglądarkach (np. V8 ) wykorzystuje techniki kompilacji JIT.Innymi słowy, różnica między tłumaczami a kompilatorami jest bardzo rozmyta (w rzeczywistości istnieje między nimi kontinuum), a praktycznie mówiąc, większość implementacji języka programowania często ma zarówno aspekt interpretera, jak i kompilatora (przynajmniej do kodu bajtowego).
Implementacja może być szybka lub powolna niezależnie od użycia większości technik podobnych do „kompilatora” lub „interpretera”.
Niektóre cechy językowe sprzyjają podejściu do tłumaczenia (i można je efektywnie skompilować tylko poprzez analizę całego programu ).
W przypadku niektórych rodzajów problemów warto zaprojektować oprogramowanie z niektórymi metodami metaprogramowania i zapewnia ono znaczne przyspieszenie. Można sobie wyobrazić, że biorąc pod uwagę określone dane wejściowe, program dynamicznie generuje specjalistyczny kod do jego przetworzenia. Jest to nawet możliwe w przypadku C lub C ++ (przy użyciu biblioteki JIT lub wygenerowaniu kodu C, kompilacji jako wtyczki, która jest ładowana dynamicznie).
Zobacz także to powiązane pytanie dotyczące Pythona i tamto
źródło
W przypadku kodu takiego
A = A + B
można skompilować do jednej lub dwóch instrukcji maszynowych, z których każda zajmuje określoną liczbę cykli. Żaden tłumacz nie może zrobić tego samego w tej liczbie cykli z prostego powodu.Tłumacz interpretuje również własny zestaw instrukcji (nazywaj je kodami bajtowymi, kodami p, językiem pośrednim itp.). Za każdym razem, gdy widzi kod bajtowy, taki jak ADD, musi go jakoś wyszukać i rozgałęzić się do kodu, który dokonuje dodania.
Następnym razem to widzi, że musi powtarzać tego odnośnika, chyba, że ma sposób na zapamiętanie uprzedniej odnośnika. Jeśli ma sposób na zapamiętanie wcześniejszego wyszukiwania, nie jest to już tak zwany „tłumacz”, ale raczej kompilator „just-in-time” lub JITter.
Z drugiej strony...
W przypadku kodu
callSomeFunction( ... some args ...)
, ile cykli spędzonych między wprowadzeniem tego kodu a jego pozostawieniem? Wszystko zależy od tego, co dzieje się w środkucallSomeFunction
. Może to być kilka, a może tryliony, nawet jeślicallSomeFunction
sam zostanie skompilowany. Jeśli to dużo, nie ma sensu dyskutować o koszcie interpretacji tego wiersza kodu - pieniądze są gdzie indziej.Pamiętaj, że interpretowane języki mają swoją wartość, np. Nie trzeba ich kompilować. („Kompilacja” składni powierzchni do kodów bajtowych zajmuje trywialny czas. Weźmy na przykład R lub MATLAB.)
Potrzebna jest także elastyczność inteligentnych poziomów programowania. W Minsky's Society of Mind , rozdział 6.4 B -Brains, są programy A, które zajmują się światem, i są programy B, które zajmują się programami A, i mogą być dalsze poziomy. Programy, które piszą i zarządzają innymi programami, mogą być łatwiej wykonywane w systemach interpretacyjnych.
W Lisp możesz pisać,
(+ A B)
aby dodać A i B, ale po napisaniu masz tylko opcję, aby go uruchomić lub nie. Możesz także napisać,(eval (list '+ 'A 'B))
który konstruuje program, a następnie wykonuje go. Może skonstruować coś innego.Przedmiotem programu jest inny program . Łatwiej jest pisać w tłumaczonym języku (jednak, jak zauważa Jörg, nowsze wersje Lisp, podczas gdy mają możliwość
eval
kompilacji w locie, więc nie mają kary za tłumaczenie).źródło
eval
iapply
funkcje, które są tłumaczami.eval
nie jest interpretowane. I nie maapply
. Z pewnością istnieją implementacje, które zawierają tłumaczy, ale SBCL nie.eval
is not interpret ed . Jest to interpretować er .Rodzaj, w pewnym sensie, zależy, ale zgodnie z ogólną zasadą skompilowane - czy to przez JIT, czy statycznie skompilowane - środowisko będzie szybsze dla wielu zadań wymagających dużej mocy obliczeniowej - zakładając dla uproszczenia ten sam język.
Częściowo dlatego, że tłumaczone języki muszą mieć pętlę tłumacza, która czyta instrukcję, wybiera odpowiednią akcję do wykonania i wykonuje ją. W najlepszym przypadku, takim jak interpretacja kodu bajtowego Pythona lub Javy (tak jak robił to stary JVM), ma narzut kilku instrukcji i spowodował spustoszenie za pomocą predyktora gałęzi - bez ostatniej można spodziewać się ogromnych kar z powodu nieprzewidzianych zdarzeń. Nawet bardzo głupi JIT powinien to znacznie przyspieszyć.
To powiedziawszy, język interpretowany może oszukiwać. Na przykład Matlab ma zoptymalizowane procedury mnożenia macierzy i po kilku zmianach możesz uruchomić kod na GPU (zastrzeżenie: pracuję dla nVidii - każda wyrażona tutaj opinia jest moja i nie reprezentuje poglądu mojego pracodawcy). W ten sposób możesz pisać krótki i mocny kod wyższego poziomu, nie martwiąc się o szczegóły - ktoś się nim zajął i poświęcił czas i zasoby na jego optymalizację w języku niskiego poziomu. Nie ma w nim niczego odziedziczonego i nie zapobiega to, na przykład, Matlabowi do JIT kodu, ale często nie ma żadnego powodu, ponieważ narzut wywołania rutyny wysokiego poziomu jest minimalny w porównaniu z czasem spędzonym na niskim poziomie.
TL; DR - skompilowane programy mają ogromną przewagę wydajności nad interpretowanymi (porównanie jabłek z jabłkami patrz PyPy Speed ). Jednak szybkość pliku wykonywalnego jest tylko częścią problemu i może nie mieć większego wpływu na ogólną szybkość (jeśli czas jest spędzany głównie w bibliotekach). Liczy się także wdrożenie.
źródło
Twoje założenie jest uzasadnione, chociaż jest założeniem.
Nie zamierzam omawiać powodów, dla których skompilowany kod powinien być szybszy niż kod interpretowany: jeśli wiesz, jak działają komputery, będzie to oczywiste. Różnicą mogą być rzędy wielkości dla niektórych rodzajów problemów. Jeśli Twój recenzent poważnie kwestionuje ten ogólny przypadek, nie wie, o czym mówi.
Mogą mieć jednak rację, czy różnica jest znacząca w rodzaju tworzonej aplikacji. Jeśli jest to głównie We / Wy lub w większości wywoływanie bibliotek skompilowanych i nie ma dużo obliczeń, narzut związany z procesem interpretacji może być nieznaczny.
Ale mój post jest następujący: jako ekspert IT będziesz często wezwany do podejmowania szybkich decyzji w oparciu o ogólną wiedzę o tym, jak powinno działać. Wykonanie określonego testu może dać bardziej dokładną odpowiedź, ale będzie kosztować znacznie więcej i nie doprowadzi cię tam pierwszy.
Ale od czasu do czasu dasz się złapać. Zdarzyło mi się. Dokonujesz dobrego założenia, a potem okazuje się, że nie wziąłeś pod uwagę głupoty świata.
Ale nie potrafię wyjaśnić tak dobrze, jak moja ulubiona kreskówka Dilberta wszechczasów. Nic nie pokazuje lepiej niż niebezpieczeństwo bycia mądrym dupkiem.
TL; DR: powinieneś mieć rację, ale na wszelki wypadek sprawdź prawdziwy świat.
źródło
O ile nie użyjesz czegoś nieco egzotycznego, twoim problemem nie będzie wydajność w interpretowanym języku A i kompilowanym języku B.
Ponieważ jeśli ty / twój zespół znasz A, a nie B, a więc piszesz o wiele lepszy kod w A niż B, możesz osiągnąć znacznie lepszą wydajność w A niż B. Jeśli masz ludzi znających jeden język, a język / biblioteki mogą praca, której potrzebujesz, trzymaj się jej.
Oto link o wyrażeniach regularnych w różnych językach; zobaczysz, że regex są lepiej zaimplementowane w niektórych językach, nawet jeśli są skompilowane lub nie: http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna
źródło
Myślę, że mówienie o wydajności dwóch technologii po prostu nie jest dobrym pomysłem, ponieważ jedna jest kompilowana, a druga interpretowana. Jak stwierdzono w innych odpowiedziach, może to zależeć od obszaru zastosowania (niektóre języki mogą być zoptymalizowane, aby wykonywać niektóre operacje bardzo szybko i wykonywać inne rzeczy wolniej), a także od doświadczenia osób, które będą korzystać z tej technologii.
Nie sądzę, że uzasadnione jest oczekiwanie, że zwiększysz wydajność, jeśli weźmiesz kilka znakomitych koderów interpretowanych języków i zapewnisz im technologię, której nie znają - może teoretycznie ta ostatnia MOŻE przynieść lepszą wydajność, ale w rzeczywistości, bez niezbędnych umiejętności i doświadczenia nie wykorzystasz wszystkich możliwości optymalizacji.
Od jednego ze znanych pracowników firmy z Doliny Krzemowej słyszałem również, że wolą język, który jest prostszy w użyciu, ponieważ płacenie niektórym wykwalifikowanym programistom za bardziej skomplikowany, ale wysoce zoptymalizowany kod jest bardziej kosztowne i kłopotliwe niż po prostu kup więcej sprzętu, aby poradzić sobie z mniej wydajnym wdrażaniem, dlatego też należy wziąć to pod uwagę przy wyborze technologii.
źródło
Kiedyś musiałem wydać podobne oświadczenie, aby uzasadnić wielką decyzję.
Po pierwsze, mogą nie chcieć wierzyć w skromnego inżyniera, więc znalazłem porównywalne testy porównawcze i zacytowałem je. Jest ich wiele, od ludzi takich jak Microsoft czy renomowane uniwersytety. I powiedzą coś takiego: Metoda A jest od 3 do 10 razy szybsza niż metoda B, w zależności od zmiennych X i Y.
Po drugie, możesz chcieć uruchomić własny test porównawczy, być może używając reprezentatywnego fragmentu danego kodu lub czegoś podobnego, co już masz. Uruchom go 1000 razy w ciągu nocy, więc naprawdę jest mierzalna różnica.
W tym momencie różnica (lub jej brak) między A i B powinna być tak wyraźna, że wystarczy tylko ją przedstawić. Dlatego sformatuj wyniki wyraźnie, z diagramami, jeśli to możliwe, podając wszystkie założenia i definiując wszystkie użyte dane.
źródło
Argumentowałbym, że każdy język dynamiczny ma przewagę nad językami kompilowanymi statycznie: „Optymalizacje środowiska wykonawczego”
To jeden z powodów, dla których Java może być szybsza niż C ++
Tak, ładowanie dynamicznie pisanego języka zawsze będzie kosztowało tłumaczenie i będzie niekorzystne. Jednak po uruchomieniu interpreter może profilować i poprawiać częste ścieżki kodu za pomocą informacji wykonawczych, których języki statyczne nigdy nie będą miały
UWAGA: Cóż, Java jest językiem interpretowanym, a nie dynamicznym. Jest to jednak doskonały przykład tego, co można przyspieszyć dzięki informacjom wykonawczym
źródło
To byłoby moje podejście:
Ogólnie rzecz biorąc, tłumacze ustni są kompilowani, więc każda interpretowana technologia jest niczym więcej niż skompilowaną technologią, jeśli spojrzeć na nią na niskim poziomie. Dlatego skompilowane technologie są po prostu większe, a dzięki większej liczbie możliwości nigdy nie pogorszysz się, jeśli będziesz mądry (którym ogólnie jesteś). Zależy to od tego, ile informacji jest dostępnych w czasie kompilacji i ile informacji jest dostępnych tylko w czasie wykonywania oraz od tego, jak dobre są kompilatory i tłumacze, ale teoretycznie zawsze powinno być możliwe przynajmniej wyrównanie wydajności dowolnego interpretera z odpowiednim kompilatorem, tylko dlatego, że tłumacze są wytwarzani przez kompilatory. To możliwe, nie oznacza to jednak, że dotyczy to technologii A i B.
W praktyce po prostu powiedz recenzentowi o wszystkich dostępnych testach porównawczych, w których porównywane są skompilowane i zinterpretowane systemy. Następnie poproś go o zasugerowanie tłumacza, który przebije Twój zoptymalizowany algorytm kodowany w asemblerze.
Należy dodać, że takie ogólne stwierdzenie wcale nie pomaga w porównaniu dwóch specyficznych technologii A i B. Tam wybór A i B ma o wiele, wiele większe znaczenie, niż jeśli są one interpretowane lub kompilowane.
źródło