Developer92
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
UlfZibis schrieb: Schick' doch mal 'n Link zum Benchmark Deines Vertrauens, möglichst aus dem Canonical-Repository.
Siehe Benchmarks, speziell die Phoronix Test Suite soll sehr gut sein.
Developer92 schrieb: Ich kann es halt dann möglicherweise nicht ausführen…
Welcher Mechanismus soll das den entscheiden?
Das ist genau die Frage, die mir gefehlt hatte: Der Kernel natürlich! redknight hatte da schon recht. Bei Skripten interpretiert der Kernel die Shebang, bei Kompilaten hingegen kommt das EL-Format zum Einsatz. Wobei ich jetzt nicht weiß, wie das ist, wenn ich beispielsweise einen Prozessor habe der i586 unterstützt, einen passend kompilierten Kernel und versuche ein Programm auszuführen, welches i686 benötigt. Ob das auch im ELF steht, das Programm einfach nicht läuft, der Kernel die Ausführung verweigert oder einige Instruktionen dann eben in Software nachgebildet werden. Ähnliches/Gleiches Problem dürfte man auch mit Prozessorerweiterunen haben, etwa AES-NI. Aber das wird jetzt schon arg offtopic, auch wenn ich das Thema ganz interessant finde.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
Developer92 schrieb: Ich kann es halt dann möglicherweise nicht ausführen…
Welcher Mechanismus soll das denn entscheiden?
Das ist genau die Frage, die mir gefehlt hatte: Der Kernel natürlich! redknight hatte da schon recht.
Ich meine das so: Das Userprogramm prüft, ob eine 64-Bit-CPU vorliegt, die z.B. eine spezielle Kryptoerweiterung hat. Wenn ja, kann es eine Routine aufrufen, die diese nutzt, und ist damit schneller, als die ebenfalls parallel vorliegende Routine, die mit 32-Bit-CPU-Instruktionen vorlieb nehmen muss. So kann das Programm jede CPU optimal ausnutzen. Umgekehrt: Auch ein reines nur für 32-Bit-CPUs kompilierte Programm muss prüfen, ob z.B. nur ein einfacher Atom-Prozessor vorliegt, auf dem bestimmte fortschrittlichere Instruktionen nicht implementiert sind, und dann auf langsamere Routinen ausweichen, die diese nicht enthalten. Die JAVA-HotSpot-Runtime z.B. macht davon mächtig Gebrauch. Der dort eingebettete JIT (Just-in-time-Compiler) prüft die Fähigkeiten der vorliegenden CPU, und erzeugt entsprechend mehr oder weniger optimierten Machinencode, der dann zur Ausführung gebracht wird. Der Kernel-Code bleibt da außen vor, es sei denn, er dissassembliert jedes zu ladende Programm vor der Ausführung, um zu entscheiden, ob dieses "unzulässige" Machinen-Befehle enthält, so ähnlich wie es die Virenscanner auf Windows bzgl. verdächtigem Code machen, was Windows-Programmaufrufe in der Praxis u.a. so lahm macht.
|
redknight
Moderator & Supporter
Anmeldungsdatum: 30. Oktober 2008
Beiträge: 21668
|
UlfZibis schrieb: Developer92 schrieb: Ich kann es halt dann möglicherweise nicht ausführen…
Welcher Mechanismus soll das denn entscheiden?
Das ist genau die Frage, die mir gefehlt hatte: Der Kernel natürlich! redknight hatte da schon recht.
Ich meine das so: Das Userprogramm prüft, ob eine 64-Bit-CPU vorliegt, die z.B. eine spezielle Kryptoerweiterung hat. Wenn ja, kann es eine Routine aufrufen, [...]
Himmel, nein. Ein Programm greift nicht direkt auf die CPU zu. Das tut nur der Kernel. Wenn der ein 32-Bit- Standardkernel ist, hat er die Erweiterung ncit und meldet diese somit also auch nicht an das Programm.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
redknight schrieb: Ich meine das so: Das Userprogramm prüft, ob eine 64-Bit-CPU vorliegt, die z.B. eine spezielle Kryptoerweiterung hat. Wenn ja, kann es eine Routine aufrufen, [...]
Himmel, nein. Ein Programm greift nicht direkt auf die CPU zu.
Himmel doch, es ist genau umgekehrt. Die CPU adressiert den Speicher und greift durch Laden von Maschinencode damit auf das Programm zu. Das tut nur der Kernel.
Der Kernel – welcher auch nur Programmcode ist – legt in der Adressverwaltung Speichersegmente für ein Userprogramm fest und startet dann dieses. Versucht nun dieses Programm auf Adressen außerhalb des festgelegten Segments zuzugreifen, erfolgt die berühmte segfault bzw. SIGSEGV. Wenn der ein 32-Bit- Standardkernel ist,
... verwaltet er ausschließlich Speichersegmente im 32-Bit-Adressraum. Es ist nicht Aufgabe des Kernels, die Verwendung von 64/128/256-Bit-Befehlssatzerweiterungen wie z.B. der "Kryptoerweiterung" zu verwalten, das machen Compiler! hat er die Erweiterung ncit und meldet diese somit also auch nicht an das Programm.
geht aus oben gesagtem nicht. Auch aus meiner Mitarbeit an den JAVA-Kernbibliotheken und am JAVA-Compiler weiß ich, dass über die Verwendung der vom Prozessors zur Verfügung stehenden Maschinenbefehle in diesem unabhängig vom Linux-Kernel entschieden wird. Die Java-Laufzeitumgebung, die den JIT enthält, ist aus Sicht von Linux auch nur ein Userprogramm.
|
redknight
Moderator & Supporter
Anmeldungsdatum: 30. Oktober 2008
Beiträge: 21668
|
UlfZibis schrieb: Auch aus meiner Mitarbeit am JAVA-Compiler weiß ich, dass über die Verwendung der vom Prozessors zur Verfügung stehenden Maschinenbefehle in diesem unabhängig vom Kernel entschieden wird.
Also habt ihr einen Java-JIT-Compiler, der im Kernelspace läuft, daher nicht gescheduled wird und direkt auf die Hardware zugreifen kann? Faszinierend. Laut deinem Link "Aufgaben des Kernels" tut der Kernel das: "Kontrolle des Zugriffs" und "Verteilung der Ressourcen". Das kann er nur tun, wenn er das Interface für Userspace-Programme ist, die über ihn auf die Hardware zugreifen. Das wiederum impliziert, dass er dem userspace auch nur Instruktionen zeigt und zur Verfügung stellt, die er selbst kennt. Aber nichts desto trotz: Das ist offtopic und es ist spät. Ich bin raus.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
redknight schrieb: Also habt ihr einen Java-JIT-Compiler, der im Kernelspace läuft, daher nicht gescheduled wird und direkt auf die Hardware zugreifen kann? Faszinierend.
Selbstverständlich. Das Von-Leitner-Institut bietet doch einen JIT-Compiler für verteiltest Echtzeit-Java an der das kann. Wusstest du das nicht? 🐸
UlfZibis schrieb: redknight schrieb: Himmel, nein. Ein Programm greift nicht direkt auf die CPU zu.
Himmel doch, es ist genau umgekehrt. Die CPU adressiert den Speicher und greift durch Laden von Maschinencode damit auf das Programm zu.
Äh, what? Was die CPU verarbeiten darf entscheidet der Kernel. Nur dieser hat die volle Kontrolle über die Hardware – dazwischengeschalteten Microcode nicht mitgezählt.
Es ist nicht Aufgabe des Kernels, die Verwendung von 64/128/256-Bit-Befehlssatzerweiterungen wie z.B. der "Kryptoerweiterung" zu verwalten, das machen Compiler!
Der Compiler kompiliert den Programmcode für eine bestimmte Architektur und mögliche Erweiterungen. Ich kann auf x86_64 ja auch Binaries für ARM kompilieren, gleiches gilt für Befehlssatzerweiterungen. Aber deswegen laufen sie doch nicht auf meiner x86_64 CPU…
Auch aus meiner Mitarbeit an den JAVA-Kernbibliotheken und am JAVA-Compiler weiß ich, dass über die Verwendung der vom Prozessors zur Verfügung stehenden Maschinenbefehle in diesem unabhängig vom Linux-Kernel entschieden wird. Die Java-Laufzeitumgebung, die den JIT enthält, ist aus Sicht von Linux auch nur ein Userprogramm.
Als Mitentwickler (?) von Java dürfte dir dann ja bekannt sein, dass Java-Programme eben NICHT direkt ausgeführt werden - sondern in einer JVM laufen. Die Abstraktion übernimmt hierbei die JVM. Wir sprachen oben aber von nativ lauffähigen Binaries, also Dingern die man etwa mit gcc kompiliert. Da liegen Welten dazwischen. Das ist so, als würde ich behaupten, Python-Skripte werden direkt vom Kernel ausgeführt und es gäbe dazwischen keinen Interpreter.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
redknight schrieb: UlfZibis schrieb: Auch aus meiner Mitarbeit an den JAVA-Kernbibliotheken und am JAVA-Compiler weiß ich, dass über die Verwendung der vom Prozessors zur Verfügung stehenden Maschinenbefehle in diesem unabhängig vom Linux-Kernel entschieden wird. Die Java-Laufzeitumgebung, die den JIT enthält, ist aus Sicht von Linux auch nur ein Userprogramm.
Also habt ihr einen Java-JIT-Compiler, der im Kernelspace läuft,
Nein, der läuft im Userspace. Deshalb kann er auch nur auf die vom Kernel freigegebenen Speichersegmente zugreifen. Weiterhin sind im User-Mode die Befehle und CPU-Register für die Speicherverwaltung gesperrt, damit ein Userprogramm sich nicht selbst Speichersegmente zuteilen kann, nicht aber die sonstigen 64/128/256-Bit-Befehlssatzerweiterungen, die z.B. Kompressions- und Krypto-Anwendungen beschleunigen können. daher nicht gescheduled wird
Selbstverständlich wird die Java-Laufzeitumgebung "gescheduled". und direkt auf die Hardware zugreifen kann?
Teils-teils. Für eine CPU ist jegliche Hardware nur eine Speicheradresse, egal ob RAM, Grafikkarten-Register oder Tastaturcontroller. Im Userspace sind nur die Adressbereiche unerreichbar, die der Kernel im Kernel-Mode gesperrt hat, dass können auch Teilbereiche des RAMs sein. Auf den erlaubten Teil des RAMs kann der Code des Userprogramms direkt zugreifen. Da in der 32-Bit-Archtektur Teile des möglichen Adressraums auf die "sonstige" Hardware schaltungstechnisch umgelenkt werden, sind von eingebauten 4 GiB RAM auch nur ca. 3,8 GIB nutz- und zugreifbar, auch für den Kernel. Faszinierend.
Stimmt!
Laut deinem Link "Aufgaben des Kernels" tut der Kernel das: "Kontrolle des Zugriffs" und "Verteilung der Ressourcen".
Darunter werden die Speichersegmente, vor allem die, die auf die "sonstige" Hardware umgelenkt sind, und die für die Speicherverwaltung reservierten Befehle und CPU-Register verstanden. Das kann er nur tun, wenn er das Interface für Userspace-Programme ist, die über ihn auf die Hardware,
die im User-Mode gesperrt ist, zugreifen.
Das wiederum impliziert, dass er dem userspace auch nur Instruktionen zeigt und zur Verfügung stellt, die er selbst kennt.
Ich fürchte, hier verwechselst Du Software-Instruktionen mit Maschinen-Instruktionen.
Aber nichts desto trotz: Das ist offtopic und es ist spät. Ich bin raus.
Wenn Du mir nicht glaubst, ungeachtet dass ich mich an der ein oder anderen Stelle evtl. nicht ganz fachmännisch ausgedrückt habe, kannst Du dazu ja mal die Kollegen aus dem Entwickler-Forum befragen. Developer92, falls Du auch Entwickler bist, kannst Du hier weiterhelfen?
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
Developer92 schrieb: Selbstverständlich. Das Von-Leitner-Institut bietet doch einen JIT-Compiler für verteiltest Echtzeit-Java an der das kann. Wusstest du das nicht? 🐸
Ja das mag's auch noch geben, trifft aber nicht auf die in Ubuntu üblicherweise installierte Java-Laufzeitumgebung zu.
Äh, what? Was die CPU verarbeiten darf entscheidet der Kernel.
Begrenzt, siehe voriger Post.
Der Compiler kompiliert den Programmcode für eine bestimmte Architektur und mögliche Erweiterungen.
Richtig. Pakete, die für Ubuntu-32 kompiliert sind, müssen auf dem kleinsten gemeinsamen Nenner, z.B. Pentium 4, Atom etc. lauffähig sein. Dennoch können sie Parallel-Routinen enthalten, die z.B. nur auf dem neuesten Intel i7 lauffähig sind, aber nur angesprungen werden, wenn auch eine Intel i7 CPU erkannt wird. Der Java-HotSpot-JIT-Compiler, der ja die meistdurchlaufenen Routinen – hot spots – aus dem Java-Bytecode "on-the-fly" in Maschinencode übersetzt, macht davon reichlich Gebrauch.
Als Mitentwickler (?) von Java dürfte dir dann ja bekannt sein, dass Java-Programme eben NICHT direkt ausgeführt werden - sondern in einer JVM laufen. Die Abstraktion übernimmt hierbei die JVM.
Und genau die JVM kompiliert mittels HotSpot – siehe oben – Teile des Java-Codes in native eingebettete "Binaries", die alles, was die jeweilige CPU an schnellen Befehlssatzerweiterungen bietet, ausreizt. U.a. deshalb können Java-Programme in Teilbereichen sogar schneller laufen, als C-Programme. Wir sprachen oben aber von nativ lauffähigen Binaries,
Ursprünglich sprachen wir davon, ob ein Ubuntu-32-Bit-Kernel bestimmte schnelle Befehlssatzerweiterungen, z.B. für Krypto- oder Kompressionsanwendungen, sperrt, die der 64er durchlässt, was eine Begründung dafür sein könnte, den 64er-Kernel zu bevorzugen. In dem Fall wage ich zu behaupten, dass sich der Java-JIT-Compiler als Beispiel einer nativen Anwendung diesbezüglich nicht darum schert, ob er in einem 32er- oder 64er-Ubuntu läuft. Einzig der verfügbare Adressraum ist unterschiedlich. also Dingern die man etwa mit gcc kompiliert. Da liegen Welten dazwischen.
HotSpot selbst wird mit gcc kompiliert ... gleiche Welt.
Das ist so, als würde ich behaupten, Python-Skripte werden direkt vom Kernel ausgeführt und es gäbe dazwischen keinen Interpreter.
Den gibt's in der Tat, der kann aber intern machen, was er will. Wenn ihm das Häppchen für Häppchen jede Schleife immer wieder Interpretieren zu anstrengend wird, kann er den Rotz auch kompilieren. Sogar Firefox kompiliert intern den JavaScript-Code teilweise in Maschinencode. ... und schon mal was über Jython gelesen?
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
UlfZibis schrieb: redknight schrieb:
Also habt ihr einen Java-JIT-Compiler, der im Kernelspace läuft,
Nein, der läuft im Userspace. Deshalb kann er auch nur auf die vom Kernel freigegebenen Speichersegmente zugreifen.
Ich denke redknight meinte, dass die Java-Laufzeitumgebung nur auf diejenigen Funktionen zugreifen kann, welche vom Kernel angeboten/freigegeben werden. Andernfalls müsste die JVM ja tatsächlich auf Kernelebene laufen…
Das wiederum impliziert, dass er dem userspace auch nur Instruktionen zeigt und zur Verfügung stellt, die er selbst kennt.
Ich fürchte, hier verwechselst Du Software-Instruktionen mit Maschinen-Instruktionen.
Moment, denn: Wenn ich ein Stück Hardware habe (Kryptobeschleuniger oder ähnliches), und der Kernel die Hardware nicht direkt ansprechen kann (sprich für den Kryptobeschleuniger keine Schnittstelle anbietet), so kann ich auch aus dem Userspace heraus die Hardware nicht verwenden. Denn hierzu muss der Kernel, auch wenn das Gerät nicht direkt vom Kernel verwendet werden kann, ja trotzdem eine Möglichkeit haben damit zu kommunzieren. D.h. irgendeine Schnittstelle brauche ich ja. Insofern bedingt eine vom Userspace aus erreichbare Hardware auch eine gewisse Unterstützung vom Kernel. Oder irre ich hier?
Developer92, falls Du auch Entwickler bist, kannst Du hier weiterhelfen?
Entwickler – mehr oder weniger – ja, aber eigentlich™ ganz anderes Fachgebiet. UlfZibis schrieb: Developer92 schrieb: Selbstverständlich. Das Von-Leitner-Institut bietet doch einen JIT-Compiler für verteiltest Echtzeit-Java an der das kann. Wusstest du das nicht? 🐸
Ja das mag's auch noch geben, trifft aber nicht auf die in Ubuntu üblicherweise installierte Java-Laufzeitumgebung zu.
Äh, falls das nicht verstanden wurde: Das war ein Scherz auf Basis der Beiträge von Fefe, siehe hier.
Richtig. Pakete, die für Ubuntu-32 kompiliert sind, müssen auf dem kleinsten gemeinsamen Nenner, z.B. Pentium 4, Atom etc. lauffähig sein.
Jo, dafür hat man ja Architekturbezeichnungen (i586, i686, etc.)
Dennoch können sie Parallel-Routinen enthalten, die z.B. nur auf dem neuesten Intel i7 lauffähig sind, aber nur angesprungen werden, wenn auch eine Intel i7 CPU erkannt wird.
Richtig, aber ich habe da trotzdem noch einen Einwand den ich ansprechen möchte:
Der Java-HotSpot-JIT-Compiler, der ja die meistdurchlaufenen Routinen – hot spots – aus dem Java-Bytecode "on-the-fly" in Maschinencode übersetzt, macht davon reichlich Gebrauch.
Ohne großartig zu wissen wie der Java-HotSpot-JIT-Compiler arbeitet: Prinzipiell könnte man in Java eine API anbieten, die bspw. mittels AES verschlüsselt. Ich schreibe dafür dann ein Programm. Wie dann die AES-Verschlüsselung implementiert ist hängt dann aber von meiner JVM ab, und die könnte dann beispielsweise die Verschlüsselung in Software machen (als Fallback), oder, sofern der Kernel das AES-NI-Modul geladen hat, auch direkt auf entsprechende Hardware zurückgreifen. In meinen vorherigen Posts ging ich aber davon aus, dass wir von Sprachen reden, die keine JVM oder ähnliches benötigen, also bpsw. kompilierten C-Code, der direkt (nativ) ausführbar ist. Hierbei muss ich entsprechende Hardwareunterstützung selbst entwickeln (oder auf bestehende Lösungen zurückgreifen die dann einkompiliert werden), aber der Kernel wird mir hier nicht dazwischenfunken und sagen "Hey, du hast da ja AES per Software implementiert, ich mach das jetzt aber einfach in Hardware weil's schneller geht". Das war ursprünglich mein Punkt.
U.a. deshalb können Java-Programme in Teilbereichen sogar schneller laufen, als C-Programme.
Das halte ich für ein Gerücht. Nicht, weil Java langsam wäre oder C generell schnell, sondern: Wenn ich in Java eine Befehlssatzerweiterung verwenden kann, dann steht mir diese Befehlssatzerweiterung auch in C zur Verfügung (das muss nicht hunderprozentig stimmen, aber in der Regel ist das der Fall). Wenn mein C-Code also langsamer läuft als mein Java-Code liegt das eher daran, dass ich in C die Befehlssatzerweiterung nicht nutze oder schlechten Code geschrieben habe. Java kann es hier einem durch die gegebene Abstraktion leicht machen, während in C erfahrungsgemäß viel mehr Schritte notwending sind. Ich behaupte also, dass ein C-Programm und ein Java-Programm, welche gut implementiert sind, auf identischer Hardware und bei gleicher Ausnutzung der Hardwarefunktionen gleich schnell laufen. An der Stelle sei auch erwähnt, dass ich Benchmarks zwischen Programmiersprachen weitgehend für Blödsinn halte. Meist wird da irgendein theoretisches Konstrukt verwendet, und das wird dann verglichen. Klassisches Beispiel: Ich habe eine Integervariable, welche in einer Schleife von 0 auf 1000000 zählt. Das sollte in jeder Sprache etwa gleich lange dauern, weil die Befehle der CPU immer die gleichen bleiben (im Optimalfall). Das einzige was ich aus der Laufzeit erkennen kann ist, wie gut oder schlecht der verwendete Compiler oder Interpreter läuft bzw. welche Optimierungen er verwendet, die ein anderen Compiler/Interpreter eventuell nicht verwendet. Da sieht man dann auch, wie weit ein Compiler "vorausdenken" kann. Wenn ich eine Integervariable habe, diese von 0 auf eine Million zählen lasse und die Variable dann ausgebe, dann könnte ein guter Compiler das auch abkürzen mit einem "print(1000000)". Es ist in diesem Szenario nicht nötig tatsächlich von 0 auf eine Million zu zählen, wenn ich am Ende nur die letzte Zahl ausgeben lassen. Wie gesagt, man sieht daran eher wie Compiler arbeiten, weniger wie schnell Programmiersprachen sind.
also Dingern die man etwa mit gcc kompiliert. Da liegen Welten dazwischen.
HotSpot selbst wird mit gcc kompiliert ... gleiche Welt.
Ja, aber HotSpot ist eine JVM. Mein mittels gcc kompiliertes Binary wird aber nicht noch von einer JVM ausgeführt und eventuell optimiert, sondern kann nur das, was ich hineingeschrieben habe und maximal noch gcc herausholt. Und gcc wird nicht Befehlssatzerweiterungen verwenden, die nur begrenzt verfügbar sind, wenn ich diese nicht explizit aktiviere. Was ich oben ja bereits beschrieben habe.
Den gibt's in der Tat, der kann aber intern machen, was er will. Wenn ihm das Häppchen für Häppchen jede Schleife immer wieder Interpretieren zu anstrengend wird, kann er den Rotz auch kompilieren.
Sidenote: Python-Code wird standardmäßig zu Bytecode kompiliert und dann ausgeführt, für mich also ähnlich wie Java.
. ... und schon mal was über Jython gelesen?
Natürlich, anders wäre es kaum möglich gewesen Python auf Android laufen zu lassen 😀
|
Reinarden
Anmeldungsdatum: 29. September 2014
Beiträge: 1044
|
UlfZibis schrieb: Hier nun meine Testergebnisse auf dem ASUS F200MA, 2 GiB RAM:
[..] Ich freue mich auf Eure Kommentare
Danke für diese schönen Testwerte. Sie bestätigen doch, daß 64-Bit-Programme die vielzitierten ~30% mehr Arbeitsspeicher benötigen als 32-Bit-Programme. Was bei Rechnern mit wenig Arbeitsspeicher entscheidend sein kann. Als Xubuntu-Freund installiere ich auf Rechnern mit 1 GB RAM nur 32-Bit-Xubuntu, weil ein 64-Bit-Xubuntu wegen zu wenige Arbeitsspeicher zu träge wird, auch wenn nur wenige Anwendungen laufen (Firefox, Libreoffice, uam). Hingegen auf unserem Rechner mit 2 GB RAM aus dem Jahre 2006 läuft ein 64-Bit-Xubuntu wunderbar. Deine Ausführungen über die Java-VM sind hochinteressant, auch im Hinblick auf 32- und 64-Bit. Wünsche Dir weiterhin Freude und gutes Gelingen mit Linux und Java. Nicht abschrecken lassen von grantigen Exen. Schönen Gruß von einem ehemaligen Assembler- und heutigen Java-Entwickler.
|
Reinarden
Anmeldungsdatum: 29. September 2014
Beiträge: 1044
|
Developer92 schrieb: UlfZibis schrieb:
[..] U.a. deshalb können Java-Programme in Teilbereichen sogar schneller laufen, als C-Programme.
Das halte ich für ein Gerücht.
Ist eine Tatsache, kein Gerücht; sehr vereinfacht gesagt wegen dynamischem Compilat (JIT) in einer VM versus statischem Compilat (Exe). Ausführlich beschrieben und belegt in der Fachliteratur, welche ich tatsächlich gelesen habe vor Jahren. Könnte es aber leider nicht mehr wiedergeben. Ulf wahrscheinlich schon in wenigen Sätzen. Doch ist die Frage, ob das hier zu weit führen würde.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
Reinarden schrieb: Ulf wahrscheinlich schon in wenigen Sätzen. Doch ist die Frage, ob das hier zu weit führen würde.
Ich versuch's mal kurz:
In jeder Programmiersprache ist man darauf angewiesen, fertige vorkompilierte Bibliotheken zu verwenden.
Hat man z.B. eine Bibliotheksfunktion, die die Sinus-Funktion berechnet, ist die im Fall von C schon statisch in Maschinencode compiliert, und zwar so, dass sie auf allen x86-Varianten läuft, für die sie spezifiziert ist. Manche x86-CPU's haben aber erweiterte Befehlssätze, mit denen ein Sinus schneller ausgerechnet werden kann. Für den Fall kann der Ersteller der Bibliothek vorsorgen, indem er eine Abfrage einbaut, die den tatsächlichen Befehlssatz der vorliegenden CPU feststellt, und parallel mehrere Routinen für die Sinusberechnung für unterschiedliche Befehlssätze einkompiliert, die dann abhängig vom Ergebnis der vorherigen Abfrage ausgeführt werden. Hierbei ist aber zu bedenken:
Nicht jeder Bibliotheksentwickler treibt diesen Aufwand. Selbst wenn, werden dabei, um den Aufwand in Maßen zu halten, nicht alle theoretisch verfügbaren Befehlssätze berücksichtigt. Neu eingeführte Befehlserweiterungen auf neueren x86-CPUs sind in älteren Bibliotheken nicht berücksichtigt. Die Abfrage nach den CPU-Befehlssätzen muss bei jedem Aufruf der Funktion erneut ausgeführt werden, das kostet ein wenig Zeit.
Beim JAVA-JIT-Compiler sieht die Sache anders aus, da die in JAVA-Bytecode vorliegenden Bibliotheken "dynamisch" erst zur Laufzeit in Maschinencode kompiliert werden:
Dieser Aufwand entfällt. Der Aufwand, alle denkbaren Befehlssätze zu berücksichtigen, fällt im JAVA-JIT-Compiler nur einmal an, und kann dann von allen Bibliotheken genutzt werden. Die Chance, dass neu eingeführte Befehlserweiterungen im JAVA-JIT-Compiler zeitnah eingepflegt werden, ist ziemlich hoch. Die Abfrage nach den CPU-Befehlssätzen muss vom JAVA-JIT-Compiler nur einmal ausgeführt werden, entfällt also im Code der jeweiligen Bibliotheken, wie auch der "JUMP" zur jeweiligen Unterroutine.
Zu 3.: Es gab auch schon mal einen Fall, wo darauf verzichtet wurde. Grund: Der schnelle SWAP+MOVE-Befehl ist nur im sonst eher leistungsschwachen Intel-ATOM-Prozessor implementiert, allen anderen x86-Architekturen fehlt er. Dann gibt es in der JVM weitere Optimierungen, die bei C und vor allem C++ mit statischen Vererbungen systembedingt entfallen. Googelt mal "Java schneller als C". Und wie schon gesagt, der Kernel ist da außen vor, und hat da keinen Einfluss drauf.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
Reinarden schrieb: Danke für diese schönen Testwerte. Sie bestätigen doch, daß 64-Bit-Programme die vielzitierten ~30% mehr Arbeitsspeicher benötigen als 32-Bit-Programme. Was bei Rechnern mit wenig Arbeitsspeicher entscheidend sein kann.
👍 Als Xubuntu-Freund installiere ich auf Rechnern mit 1 GB RAM nur 32-Bit-Xubuntu, weil ein 64-Bit-Xubuntu wegen zu wenige Arbeitsspeicher zu träge wird, auch wenn nur wenige Anwendungen laufen (Firefox, Libreoffice, uam). Hingegen auf unserem Rechner mit 2 GB RAM aus dem Jahre 2006 läuft ein 64-Bit-Xubuntu wunderbar.
Hast Du's da drauf denn mal mit 32-Bit-Xubuntu verglichen? Mein 2 GB ASUS ist aus dem Jahre 2013, das könnte vielleicht auch was ausmachen.
|
UlfZibis
Anmeldungsdatum: 13. Juli 2011
Beiträge: 2726
|
UlfZibis schrieb: 4. Die Abfrage nach den CPU-Befehlssätzen muss bei jedem Aufruf der Funktion erneut ausgeführt werden, das kostet ein wenig Zeit.
Das könnte z.B. der Grund für die 10 % Unterschied sein, die ich beim Test mit dem Youtube-Film bemerkt habe. Bei der 64er-Version des Videodekomprimierers können viele solcher Abfragen entfallen, da grundsätzlich von einem reichhaltigeren Befehlssatz der CPU ausgegangen werden kann.
|
Reinarden
Anmeldungsdatum: 29. September 2014
Beiträge: 1044
|
UlfZibis schrieb: Als Xubuntu-Freund installiere ich auf Rechnern mit 1 GB RAM nur 32-Bit-Xubuntu, weil ein 64-Bit-Xubuntu wegen zu wenige Arbeitsspeicher zu träge wird, auch wenn nur wenige Anwendungen laufen (Firefox, Libreoffice, uam). Hingegen auf unserem Rechner mit 2 GB RAM aus dem Jahre 2006 läuft ein 64-Bit-Xubuntu wunderbar.
Hast Du's da drauf denn mal mit 32-Bit-Xubuntu verglichen?
Nein, auf die Idee bin ich damals gar nicht gekommen. Der recht komplexe Flightgear-Flugsimulator läuft auf diesem 64-Bit-Xubuntu mit 2 GB RAM gerade noch so – er lagert aber regelmäßig aus (Swap). Da würden die ~30% weniger RAM-Verbrauch einer 32-Bit-Version sicher meßbare Unterschiede im Gesamtlaufverhalten ergeben. Da ich mich mit AMD/Intel-Maschinencode nicht auskenne, hier meine laienhafte Frage: genügt es bereits, wenn ich unter so einem 64-Bit-Ubuntu die 32-Bit-Version von Flightgear („flightgear:i386“) benutze, oder müßte es ein 32-Bit-Ubuntu mit 32-Bit-Applikationen sein, um ähnliche Ergebnisse wie Deine früher zitierten 32-64-Bit-Vergleiche zu sehen? P.S. War nicht noch ein Punkt beim Thema „Java schneller als C“ der, daß, im Gegensatz zu statisch compiliertem Maschinen-Code, die JVM das Laufzeitverhalten der Routinen untersucht und dann diese besonders optimiert, eben anhand des Laufzeitverhaltens? Während ja der statische Compiler vom Laufzeitverhalten gar nichts wissen kann.
|