Tuesday, January 08, 2008

Java Urban Legend: "Java kann kein Multi-Core"

Es ist immer wieder erstaunlich, welche Urban Legends sich über Java halten.

"Java ist langsam, zu langsam" ist davon noch der absolute Klassiker. Aktuelles Beispiel sind die Kommentare in "TWiT 126" vor ein paar Wochen.

So langsam sollte sich diese Legende doch wirklich in Luft aufgelöst haben, oder? Naja, wenn nicht, dann sollte man schnell Brian Goetz Kolumne "Java theory and practice" lesen. Insbesondere Urban performance legends und Urban performance legends, revisted. Dort heisst es zum Beispiel:

You don't have to search through too many blogs or Slashdot postings to find confidently worded statements like "Garbage collection will never be as efficient as direct memory management." And, in a way, those statements are right -- dynamic memory management is not as fast -- it's often considerably faster. The malloc/free approach deals with blocks of memory one at a time, whereas the garbage collection approach tends to deal with memory management in large batches, yielding more opportunities for optimization (at the cost of some loss in predictability).

Eine andere Legende ist, dass Java keine Multi-Prozessoren ausnutzen kann, weil es nur User-Level-Threads hat. Mir war bis heute nicht klar, dass diese Legende wirklich jemand glaubt. Aber dann hat mich ein Kommolitone, der eigentlich weiß was er tut, eines besseren belehrt.

Vermittelt wird diese Legende offenbar durch eigentlich gute Autoren wie Tanenbaum. Wenn man nach "Java User-Level" bei Google sucht, dann findet man Dutzende von Betriebssystem-Kursen, in denen genau dies gelehrt wird z.B. Uni Dortmund, Uni Mannheim und selbst, Oh Schreck, Uni Paderborn. Da muß ich wohl in KMS mal geschlafen haben. Selbst in der Wikipedia ist dies nicht eindeutig beantwortet.

Offenbar ist der Hintergrund für die Legende, dass viele immer noch bei Java 1.1. hängengeblieben sind. Dort gab es (nur) so genannte Green Threads, dies waren Javas User-Level-Threads.
Aber diese Beschränkung wurde schon mit 1.2 aufgehoben. Also vor mehr als 10 Jahren!

In "Programmieren mit Java" heisst es:

Derzeit werden Java-Threads folgendermaßen unter Windows, Solaris und Linux implementiert:
  • Unter Windows NT/2000/XP werden Java-Threads auf Threads im Betriebssystems abgebildet, die innerhalb des Virtual-Machine-Prozesses ablaufen. Die Anzahl der gestarteten Prozesse und Threads kann auf dieser Plattform gut im Task-Manager beobachtet werden. Beim Starten eines Java-Programms sieht man, dass sich die Anzahl der Prozesse um Eins erhöht, die Anzahl der Threads nimmt dagegen stärker zu. Dies ist auch dann der Fall, wenn das Programm selbst keine eigenen Threads erzeugt, weil die Virtual Machine eigene System-Threads für Aufgaben wie Garbage Collection startet.
  • Bei Solaris werden seit JDK-Version 1.2 die nativen Threads eingesetzt. In den Vorversionen machte die Solaris-Virtual Machine von Green Threads Gebrauch.
  • Unter Linux werden Threads seit JDK-Version 1.3 mit abgespalteten Tochterprozessen realisiert. Zuvor wurden auch hier Green Threads verwendet. Dadurch, dass für Java-Threads komplette Prozesse erzeugt werden, kann die Erzeugung einer großen Anzahl neuer Threads länger dauern als bei Betriebssystemen, auf denen native Threads eingesetzt werden.
Ein Blick in die Aktivitätsanzeige oder "top" hätte die Behauptung also widerlegen können.

Ans Extrem treibt es zum Beispiel die Firma "Azul Systems", die Werbung macht mit "World's Most Powerful Platform for Java Computing: Massive Capacity: 768 Processors and 768 GB of Memory".

Also: Ich hoffe, ich kann zumindest bei den Lesern dieses Blogs diese Legende aus der Welt schaffen.

Bei Autoren/Forschern aus dem Systemsoftware-Bereich bin ich schon lange sehr vorsichtig, wenn diese sich zu Software-Engineering-Themen äußern. So sehr die Autoren ihren eigenen Kram in- und auswendig kennen, so viel Mist über SE ist manchmal auch enthalten. Bestes Beispiel: "Reliable Distributed Systems". Teilweise recht grausam. Ein Paper, dass schön Distributed Computing und Software Engineering verbindet ist z.B. dieses hier.