Czy istnieje jakiś kompilator just-in-time dla skompilowanych języków, takich jak C i C ++? (Pierwsze imiona, które przychodzą na myśl, to Clang i LLVM! Ale nie sądzę, że obecnie je obsługują.)
Wyjaśnienie:
Myślę, że oprogramowanie może skorzystać z informacji zwrotnych dotyczących profilowania środowiska wykonawczego i agresywnie zoptymalizowanej ponownej kompilacji punktów aktywnych w środowisku wykonawczym, nawet w przypadku języków kompilowanych z maszyną, takich jak C i C ++.
Optymalizacja sterowana profilem wykonuje podobną pracę, ale z tą różnicą JIT byłby bardziej elastyczny w różnych środowiskach. W PGO uruchamiasz swój plik binarny przed jego wydaniem. Po wydaniu nie używałby żadnych informacji zwrotnych dotyczących środowiska / danych wejściowych zebranych w czasie wykonywania. Tak więc, jeśli wzorzec wejściowy zostanie zmieniony, grozi to obniżeniem wydajności. Ale JIT działa dobrze nawet w takich warunkach.
Jednak myślę, że jest to kontrowersyjne, czy korzyści kompilacji JIT przewyższają własne koszty.
źródło
Odpowiedzi:
[Zobacz historię edycji, aby uzyskać zupełnie inną odpowiedź, która jest teraz zasadniczo przestarzała.]
Tak, istnieje kilka kompilatorów JIT dla C i / lub C ++.
CLing (jak można się domyślać z gry) jest oparty na Clang / LLVM. Działa jak tłumacz. To znaczy, dajesz mu kod źródłowy, wydajesz komendę do uruchomienia i działa. Nacisk kładziony jest przede wszystkim na wygodę i szybką kompilację, a nie maksymalną optymalizację. Jako taka, choć technicznie odpowiedź na samo pytanie, tak naprawdę nie odpowiada to celom PO.
Inną możliwością jest NativeJIT . To pasuje nieco do pytania. W szczególności nie akceptuje kodu źródłowego C lub C ++, kompiluje go i wykonuje. Jest to raczej mały kompilator, który można skompilować w programie C ++. Akceptuje wyrażenie, które jest zasadniczo wyrażone jako EDSL w twoim programie C ++ i generuje z niego rzeczywisty kod maszynowy, który następnie możesz wykonać. To znacznie lepiej pasuje do frameworka, w którym można skompilować większość programu za pomocą normalnego kompilatora, ale ma kilka wyrażeń, których nie poznasz do czasu wykonania, które chcesz wykonać z czymś, co zbliża się do optymalnej szybkości wykonania.
Jeśli chodzi o pozorną intencję pierwotnego pytania, myślę, że podstawowy punkt mojej pierwotnej odpowiedzi nadal jest zasadny: podczas gdy kompilator JIT może dostosowywać się do takich rzeczy, jak dane, które różnią się od jednego wykonania do drugiego, a nawet zmieniają się dynamicznie podczas jednego wykonania, w rzeczywistości jest to stosunkowo niewielka różnica, przynajmniej z zasady. W większości przypadków uruchomienie kompilatora w czasie wykonywania oznacza, że musisz zrezygnować z dość dużej optymalizacji, więc najlepszym, na co zwykle masz nadzieję, jest to, że jest on tak szybki, jak mógłby to zrobić konwencjonalny kompilator.
Chociaż można postulować sytuacje, w których informacje dostępne dla kompilatora JIT mogłyby pozwolić mu wygenerować znacznie lepszy kod niż konwencjonalny kompilator, przypadki tego typu w praktyce wydają się dość niezwykłe (iw większości przypadków, w których udało mi się zweryfikować tak się dzieje, tak naprawdę było to spowodowane problemem w kodzie źródłowym, a nie statycznym modelem kompilacji).
źródło
Tak, istnieją kompilatory JIT dla C ++. Z czystego punktu widzenia wydajność, myślę, że profilowana optymalizacja (PGO) jest nadal lepsza.
Nie oznacza to jednak, że kompilacja JIT nie jest jeszcze stosowana w praktyce. Na przykład Apple używa LLVM jako JIT dla potoku OpenGL. Jest to domena, w której masz znacznie więcej informacji w czasie wykonywania, których można użyć do usunięcia dużej ilości martwego kodu.
Inną interesującą aplikacją JIT jest Cling, interaktywny interpreter C ++ oparty na LLVM i Clang: https://root.cern.ch/cling
Oto przykładowa sesja:
Nie jest to projekt zabawkowy, ale w rzeczywistości jest wykorzystywany na przykład w CERN-ie do opracowania kodu dla dużego zderzacza hadronów.
źródło
C ++ / CLI jest odrzucony. To prawda, że C ++ / CLI nie jest C ++, ale jest całkiem blisko. To powiedziawszy, JIT Microsoftu nie robi super sprytnych / uroczych rodzajów optymalizacji opartych na zachowaniu środowiska uruchomieniowego, o które pytasz, przynajmniej o ile mi wiadomo. To naprawdę nie pomaga.
http://nestedvm.ibex.org/ zmienia MIPS w kod bajtowy Java, który zostałby następnie odrzucony. Problem z tym podejściem z twojego pytania polega na tym, że wyrzucasz wiele przydatnych informacji, zanim dotrze do JIT.
źródło
Po pierwsze, zakładam, że chcesz jit śledzenia, a nie jit metody.
Najlepszym podejściem byłoby skompilowanie kodu do llvm IR, a następnie dodanie kodu śledzenia przed utworzeniem natywnego pliku wykonywalnego. Gdy blok kodu zostanie wystarczająco dobrze wykorzystany i gdy zgromadzona zostanie wystarczająca ilość informacji o wartościach zmiennych (nie typach jak w językach dynamicznych), kod może zostać ponownie skompilowany (z IR) za pomocą osłon opartych na wartościach zmiennych.
Wydaje mi się, że pamiętam pewne postępy w tworzeniu jit ac / c ++ w clangu pod nazwą libclang.
źródło