Da immer wieder ein Kampf zu herrschen scheint zwischen der
Managed-Code-Fraktion und Leuten die lieber native-languages haben
(es gibt natürlich auch was dazwischen, wie zum Beispiel go, das eine
relativ schlanke Runtime hat und nicht wie Java fast alles versucht
dynamisch zu prüfen), versuche ich mal eine differenziertere Sicht
darzulegen (hoffe mir gelingt das).
Vorweg zu meinem Background: ich mache System-Programmierung
(Datenbanken) fast ausschliesslich mit C++.
Die C/C++-Fraktion bringt immer wieder das Argument, ein Garbage
Collector mache ein Programm langsam. Das ist so falsch (oder
wenigstens nicht ganz richtig):
- Ein GC beschleunigt die meisten Programme sogar, da zum Beispiel
(falls gut implementiert - also wie zum Beispiel jener von Java oder
.NET) die Locality verbessert und das Allozierung von neuem Speicher
schneller ist. Natürlich stimmt das nicht mehr, sobald man anfängt,
sein eigenes für den jeweiligen Use-Case optimiertes
Memory-Management zu schreiben. Für eine GUI-Anwendung oder ein
Servlet ist das aber meistens schlicht übertrieben.
- Reference-Counting ist nicht schneller als Garbage Collection. Im
Gegenteil: häufig ist es sehr langsam (vor allem falls es nicht
vorsichtig genug benutzt wird), da halt Referenzen gezählt werden
müssen. Der Hauptvorteil von Reference-Counting ist einfach, dass es
deterministisch ist, was aber halt nur für gewisse Anwendungen
wichtig ist.
- Ein GC unterbricht normalerweise nicht das Programm, sondern läuft
in einem anderen Thread (Tri-Color GC). Je nach Implementierung wird
zwar ab und zu ein kompletter Mark and Sweep gemacht, allerdings
passiert das dann sehr selten und ist wieder in den meisten Fällen
nicht weiter von Belang.
Auch sonst gibt es immer wieder Gerüchte, warum Java langsam ist.
Allerdings ist Java nicht wirklich langsam (dass das Starten zum Teil
lange dauert, liegt unter anderem daran dass Java dynamisch optimiert
wird und wieder "deoptimiert" werden muss, falls sich der Klassenbaum
ändert, da zum Beispiel ein neues Jar nachgeladen wurde - das erklärt
unter anderem auch, warum Eclipse so lange zum starten braucht). Es
ist einfach so, dass viele Java-Programmierer zu wenig Wert auf
Performance legen. Wenn man sich Benchmarks von Java vs C++ anschaut,
ist Java meistens maximal 10-20 % langsamer als C++ - ein Unterschied
der dem Benutzer bei den meisten Anwendungen nicht auffällt (die
meisten Programme verbringen 90% ihrer Zeit mit I/O-Operationen - und
das ist bei C++ genau so langsam wie bei Java). Was allerdings stimmt
ist, dass Java-Programme unheimlich viel Speicher fressen. Das hat
verschiedene Gründe (Laufzeitinformationen und imho auch ein paar
Design-Fehler der Sprache selber). Das ganze wird dadurch noch
schlimmer, dass die JVM nie Speicher an das Betriebssystem zurück
gibt.
Also mal mein erstes Fazit: für 80-90 % aller Anwendungen sind
managed Sprachen sehr gut geeignet. Sie erhöhen die Produktivität und
vermeiden viele Fehler. Zudem richten mittelmässig talentierte
Programmierer in einem Java-Projekt viel weniger Schaden an, als in
einem C++-Projekt (und 80% aller Menschen die sich Informatiker
nennen sind nicht mal mittelmässig gute Programmierer sondern einfach
nur Bastler die man eigentlich nie an ein seriöses Projekt lassen
sollte). Dass man mal einen schlechten Programmierer einstellt ist ab
einer gewissen Team-Grösse kaum zu vermeiden - und es ist oft
beeindruckend, wie viel ein einzelner in ein paar Monaten kaputt
machen kann.
Auch wenn es sich nun nicht daran anhört, sehe ich mich nicht in der
Fraktion der managed-code Apostel. Für gewisse Use-Cases
(Betriebssysteme, Datenbanken, Compiler etc) halte ich Sprachen wie
Java und C# für komplett ungeeignet. Unter anderem da
- Java einfach zu Speicherhungrig ist (in einer Datenbank will ich so
viel wie möglich des freien Speichers für Caching benutzen).
- Java einen gewissen nicht-determinismus einführt, weil es eben
einen Garbage Collector hat.
- Managed code performed oft schlecht, wenn man sehr viel Speicher
immer wieder alloziert und wieder dealloziert - hier ist eine eigene
Speicherverwaltung bereits ein muss (wir haben hier eine
Test-Datenbank in Java und in den Benchmarks sieht man beim Graphen
einbuchtungen, sobald der GC einspringt. Setzt man das System unter
sehr hohe last, fällt der Throughput plötzlich auf 0 für etwa 10
Minuten - so ein Verhalten ist ein absoluter show-stopper für eine
DB).
FAZIT: ich bin überzeugt, dass beide Sprachfamillien ihre
Berechtigung haben und dass für sehr vieles eine Sprache wie Java
oder C# sehr sehr gut geeignet ist. Trotzdem sind System-Sprachen wie
C/C++ enorm wichtig und ich schaue mit viel Interesse zu Rust!
Managed-Code-Fraktion und Leuten die lieber native-languages haben
(es gibt natürlich auch was dazwischen, wie zum Beispiel go, das eine
relativ schlanke Runtime hat und nicht wie Java fast alles versucht
dynamisch zu prüfen), versuche ich mal eine differenziertere Sicht
darzulegen (hoffe mir gelingt das).
Vorweg zu meinem Background: ich mache System-Programmierung
(Datenbanken) fast ausschliesslich mit C++.
Die C/C++-Fraktion bringt immer wieder das Argument, ein Garbage
Collector mache ein Programm langsam. Das ist so falsch (oder
wenigstens nicht ganz richtig):
- Ein GC beschleunigt die meisten Programme sogar, da zum Beispiel
(falls gut implementiert - also wie zum Beispiel jener von Java oder
.NET) die Locality verbessert und das Allozierung von neuem Speicher
schneller ist. Natürlich stimmt das nicht mehr, sobald man anfängt,
sein eigenes für den jeweiligen Use-Case optimiertes
Memory-Management zu schreiben. Für eine GUI-Anwendung oder ein
Servlet ist das aber meistens schlicht übertrieben.
- Reference-Counting ist nicht schneller als Garbage Collection. Im
Gegenteil: häufig ist es sehr langsam (vor allem falls es nicht
vorsichtig genug benutzt wird), da halt Referenzen gezählt werden
müssen. Der Hauptvorteil von Reference-Counting ist einfach, dass es
deterministisch ist, was aber halt nur für gewisse Anwendungen
wichtig ist.
- Ein GC unterbricht normalerweise nicht das Programm, sondern läuft
in einem anderen Thread (Tri-Color GC). Je nach Implementierung wird
zwar ab und zu ein kompletter Mark and Sweep gemacht, allerdings
passiert das dann sehr selten und ist wieder in den meisten Fällen
nicht weiter von Belang.
Auch sonst gibt es immer wieder Gerüchte, warum Java langsam ist.
Allerdings ist Java nicht wirklich langsam (dass das Starten zum Teil
lange dauert, liegt unter anderem daran dass Java dynamisch optimiert
wird und wieder "deoptimiert" werden muss, falls sich der Klassenbaum
ändert, da zum Beispiel ein neues Jar nachgeladen wurde - das erklärt
unter anderem auch, warum Eclipse so lange zum starten braucht). Es
ist einfach so, dass viele Java-Programmierer zu wenig Wert auf
Performance legen. Wenn man sich Benchmarks von Java vs C++ anschaut,
ist Java meistens maximal 10-20 % langsamer als C++ - ein Unterschied
der dem Benutzer bei den meisten Anwendungen nicht auffällt (die
meisten Programme verbringen 90% ihrer Zeit mit I/O-Operationen - und
das ist bei C++ genau so langsam wie bei Java). Was allerdings stimmt
ist, dass Java-Programme unheimlich viel Speicher fressen. Das hat
verschiedene Gründe (Laufzeitinformationen und imho auch ein paar
Design-Fehler der Sprache selber). Das ganze wird dadurch noch
schlimmer, dass die JVM nie Speicher an das Betriebssystem zurück
gibt.
Also mal mein erstes Fazit: für 80-90 % aller Anwendungen sind
managed Sprachen sehr gut geeignet. Sie erhöhen die Produktivität und
vermeiden viele Fehler. Zudem richten mittelmässig talentierte
Programmierer in einem Java-Projekt viel weniger Schaden an, als in
einem C++-Projekt (und 80% aller Menschen die sich Informatiker
nennen sind nicht mal mittelmässig gute Programmierer sondern einfach
nur Bastler die man eigentlich nie an ein seriöses Projekt lassen
sollte). Dass man mal einen schlechten Programmierer einstellt ist ab
einer gewissen Team-Grösse kaum zu vermeiden - und es ist oft
beeindruckend, wie viel ein einzelner in ein paar Monaten kaputt
machen kann.
Auch wenn es sich nun nicht daran anhört, sehe ich mich nicht in der
Fraktion der managed-code Apostel. Für gewisse Use-Cases
(Betriebssysteme, Datenbanken, Compiler etc) halte ich Sprachen wie
Java und C# für komplett ungeeignet. Unter anderem da
- Java einfach zu Speicherhungrig ist (in einer Datenbank will ich so
viel wie möglich des freien Speichers für Caching benutzen).
- Java einen gewissen nicht-determinismus einführt, weil es eben
einen Garbage Collector hat.
- Managed code performed oft schlecht, wenn man sehr viel Speicher
immer wieder alloziert und wieder dealloziert - hier ist eine eigene
Speicherverwaltung bereits ein muss (wir haben hier eine
Test-Datenbank in Java und in den Benchmarks sieht man beim Graphen
einbuchtungen, sobald der GC einspringt. Setzt man das System unter
sehr hohe last, fällt der Throughput plötzlich auf 0 für etwa 10
Minuten - so ein Verhalten ist ein absoluter show-stopper für eine
DB).
FAZIT: ich bin überzeugt, dass beide Sprachfamillien ihre
Berechtigung haben und dass für sehr vieles eine Sprache wie Java
oder C# sehr sehr gut geeignet ist. Trotzdem sind System-Sprachen wie
C/C++ enorm wichtig und ich schaue mit viel Interesse zu Rust!