Ich bin auf Xamarin-Behauptungen gestoßen, dass ihre Mono-Implementierung auf Android und ihre C # -kompilierten Apps schneller sind als Java-Code. Hat jemand tatsächliche Benchmarks für sehr ähnlichen Java- und C # -Code auf verschiedenen Android-Plattformen durchgeführt, um solche Behauptungen zu überprüfen, konnte er den Code und die Ergebnisse veröffentlichen?
Hinzugefügt am 18. Juni 2013
Da es keine Antwort gab und solche von anderen durchgeführten Benchmarks nicht finden konnten, entschied ich mich, meine eigenen Tests durchzuführen. Leider bleibt meine Frage "gesperrt", so dass ich dies nicht als Antwort posten kann, sondern nur die Frage bearbeiten kann. Bitte stimmen Sie ab, um diese Frage erneut zu öffnen. Für C # habe ich Xamarin.Android Ver verwendet. 4.7.09001 (Beta). Der Quellcode, alle Daten, die ich zum Testen und Kompilieren von APK-Paketen verwendet habe, befinden sich auf GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C #: https://github.com/gregko/TtsSetup_C_sharp
Wenn jemand meine Tests auf anderen Geräten oder Emulatoren wiederholen möchte, wäre ich interessiert, auch die Ergebnisse zu erfahren.
Ergebnisse meiner Tests
Ich habe meine Klasse zum Extrahieren von Sätzen auf C # portiert (aus meiner @ Voice Aloud Reader-App) und einige Tests mit 10 HTML-Dateien in Englisch, Russisch, Französisch, Polnisch und Tschechisch durchgeführt. Jeder Lauf wurde 5 Mal für alle 10 Dateien durchgeführt. Die Gesamtzeit für 3 verschiedene Geräte und einen Emulator ist unten angegeben. Ich habe nur "Release" Builds getestet, ohne dass das Debuggen aktiviert war.
HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM
Java: Gesamtsumme der Zeit (5 Läufe): 12361 ms, mit einer Gesamtlesezeit von 13304 ms
C #: Gesamtsumme der Zeit (5 Läufe): 17504 ms, mit einer Gesamtlesezeit von 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: Gesamtsumme (5 Läufe): 8947 ms, mit einer Lesesumme von 9186 ms
C #: Gesamtsumme der Zeit (5 Läufe): 9884 ms, mit einer Gesamtlesezeit von 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: Gesamtsumme (5 Läufe): 9742 ms, mit einer Lesesumme von 10111 ms
C #: Gesamtsumme (5 Läufe): 10459 ms, mit einer Lesesumme von 10696 ms
Emulator - Intel (Android 4.2, API 17)
Java: Gesamtsumme der Zeit (5 Läufe): 2699 ms, mit einer Gesamtlesezeit von 3127 ms
C #: Gesamtsumme der Zeit (5 Läufe): 2049 ms, mit einer Gesamtlesezeit von 2182 ms
Emulator - Intel (Android 2.3.7, API 10)
Java: Gesamtsumme der Zeit (5 Läufe): 2992 ms, mit einer Gesamtlesezeit von 3591 ms
C #: Gesamtsumme der Zeit (5 Läufe): 2049 ms, mit einer Gesamtlesezeit von 2257 ms
Emulator - Arm (Android 4.0.4, API 15)
Java: Gesamtsumme der Zeit (5 Läufe): 41751 ms, mit einer Gesamtlesezeit von 43866 ms
C #: Gesamtsumme der Zeit (5 Läufe): 44136 ms, mit einer Gesamtlesezeit von 45109 ms
Kurze Diskussion
Mein Testcode enthält hauptsächlich Textanalyse, Ersetzen und Regex-Suche. Möglicherweise sind die Ergebnisse für anderen Code (z. B. mehr numerische Operationen) anders. Auf allen Geräten mit ARM-Prozessoren schnitt Java besser ab als Xamarin C # -Code. Der größte Unterschied bestand unter Android 2.3, wo C # -Code mit ca. 70% der Java-Geschwindigkeit.
Auf dem Intel-Emulator (mit Intel HAX-Technologie läuft der Emulator im Fast-Virt-Modus) führt Xamarin C # -Code meinen Beispielcode viel schneller aus als Java - ungefähr 1,35-mal schneller. Vielleicht sind der Code und die Bibliotheken der virtuellen Mono-Maschine unter Intel viel besser optimiert als unter ARM?
Bearbeiten 8. Juli 2013
Ich habe gerade den Genymotion Android-Emulator installiert, der in Oracle VirtualBox ausgeführt wird, und auch dieser verwendet einen nativen Intel-Prozessor, der keinen ARM-Prozessor emuliert. Wie beim Intel HAX Emulator läuft auch hier C # viel schneller. Hier sind meine Ergebnisse:
Genymotion-Emulator - Intel (Android 4.1.1, API 16)
Java: Gesamtsumme (5 Läufe): 2069 ms, mit einer Lesesumme von 2248 ms
C #: Gesamtsumme der Zeit (5 Läufe): 1543 ms, mit einer Lesesumme von 1642 ms
Ich bemerkte dann, dass es ein Update für Xamarin.Android Beta, Version 4.7.11 gab, mit Versionshinweisen, in denen auch einige Änderungen in der Mono-Laufzeit erwähnt wurden. Beschlossen, einige ARM-Geräte schnell zu testen, und große Überraschung - C # -Nummern verbessert:
BN Nook XD +, ARM (Android 4.0)
Java: Gesamtsumme (5 Läufe): 8103 ms, mit einer Lesesumme von 8569 ms
C #: Gesamtsumme (5 Läufe): 7951 ms, mit einer Lesesumme von 8161 ms
Beeindruckend! C # ist jetzt besser als Java? Beschlossen, den Test auf meinem Galaxy Note 2 zu wiederholen:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: Gesamtsumme (5 Läufe): 9675 ms, mit einer Lesesumme von 10028 ms
C #: Gesamtsumme (5 Läufe): 9911 ms, mit einer Lesesumme von 10104 ms
Hier scheint C # nur geringfügig langsamer zu sein, aber diese Zahlen gaben mir eine Pause: Warum ist die Zeit länger als bei Nook HD +, obwohl Note 2 einen schnelleren Prozessor hat? Die Antwort: Energiesparmodus. In Nook war es deaktiviert, in Note 2 aktiviert. Beschlossen, mit deaktiviertem Energiesparmodus zu testen (wie aktiviert aktiviert, begrenzt es auch die Prozessorgeschwindigkeit):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), Energiesparen deaktiviert
Java: Gesamtsumme der Zeit (5 Läufe): 7153 ms, mit einer Gesamtlesezeit von 7459 ms
C #: Gesamtsumme (5 Läufe): 6906 ms, mit einer Lesesumme von 7070 ms
Jetzt ist C # überraschenderweise auch auf dem ARM-Prozessor etwas schneller als Java. Großer Fortschritt!
Bearbeiten 12. Juli 2013
Wir alle wissen, dass nichts besser ist als nativer Code, und ich war mit der Leistung meines Satzteilers in Java oder C # nicht zufrieden, insbesondere, dass ich ihn verbessern (und damit noch langsamer machen) muss. Beschlossen, es in C ++ neu zu schreiben. Hier ist ein kleiner (dh aus anderen Gründen kleinerer Satz von Dateien als bei früheren Tests) Vergleich der Geschwindigkeit von nativem mit Java auf meinem Galaxy Note 2 bei deaktiviertem Energiesparmodus:
Java: Gesamte Gesamtzeit (5 Läufe): 3292 ms, mit einer Gesamtlesezeit von 3454 ms
Native Daumen: Gesamtsumme der Zeit (5 Läufe): 537 ms, mit einer Gesamtlesezeit von 657 ms
Native Arm: Gesamte Gesamtzeit (5 Läufe): 458 ms, mit einer Gesamtlesezeit von 587 ms
Sieht für meinen speziellen Test so aus, als wäre der native Code 6 bis 7 Mal schneller als Java. Vorsichtsmaßnahme: Die Klasse std :: regex konnte unter Android nicht verwendet werden. Daher musste ich meine eigenen speziellen Routinen schreiben, um nach Absatzumbrüchen oder HTML-Tags zu suchen. Meine ersten Tests desselben Codes auf einem PC mit Regex waren etwa vier- bis fünfmal schneller als bei Java.
Puh! Als ich wieder mit char * oder wchar * Zeigern die rohe Erinnerung weckte, fühlte ich mich sofort 20 Jahre jünger! :) :)
Bearbeiten 15. Juli 2013
(Weitere Informationen zu besseren Ergebnissen mit Dot42 finden Sie weiter unten mit den Änderungen vom 30.07.2013.)
Mit einigen Schwierigkeiten gelang es mir, meine C # -Tests auf Dot42 (Version 1.0.1.71 Beta) zu portieren, eine andere C # -Plattform für Android. Vorläufige Ergebnisse zeigen, dass Dot42-Code auf einem Intel Android-Emulator etwa dreimal (dreimal) langsamer ist als Xamarin C # (Version 4.7.11). Ein Problem ist, dass die System.Text.RegularExpressions-Klasse in Dot42 nicht über die Split () -Funktion verfügt, die ich in Xamarin-Tests verwendet habe. Daher habe ich stattdessen die Java.Util.Regex-Klasse und Java.Util.Regex.Pattern.Split () verwendet. An dieser Stelle im Code gibt es also diesen kleinen Unterschied. Sollte aber kein großes Problem sein. Dot42 kompiliert zu Dalvik (DEX) -Code, arbeitet also nativ mit Java auf Android zusammen und benötigt kein teures Interop von C # nach Java wie Xamarin.
Zum Vergleich führe ich den Test auch auf ARM-Geräten durch - hier ist der Dot42-Code "nur" 2x langsamer als Xamarin C #. Hier sind meine Ergebnisse:
HTC Nexus One Android 2.3.7 (ARM)
Java: Gesamtsumme (5 Läufe): 12187 ms, mit einer Lesesumme von 13200 ms
Xamarin C #: Gesamtsumme (5 Läufe): 13935 ms, mit einer Lesesumme von 14465 ms
Dot42 C #: Gesamtsumme (5 Läufe): 26000 ms, mit einer Lesesumme von 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: Gesamtsumme (5 Läufe): 6895 ms, mit einer Lesesumme von 7275 ms
Xamarin C #: Gesamtsumme (5 Läufe): 6466 ms, mit einer Gesamtlesezeit von 6720 ms
Dot42 C #: Gesamtsumme (5 Läufe): 11185 ms, mit einer Lesesumme von 11843 ms
Intel Emulator, Android 4.2 (x86)
Java: Gesamtsumme (5 Läufe): 2389 ms, mit einer Lesesumme von 2770 ms
Xamarin C #: Gesamtsumme der Zeit (5 Läufe): 1748 ms, mit einer Gesamtlesezeit von 1933 ms
Dot42 C #: Gesamtsumme der Zeit (5 Läufe): 5150 ms, mit einer Gesamtlesezeit von 5459 ms
Für mich war es auch interessant festzustellen, dass Xamarin C # auf einem neueren ARM-Gerät etwas schneller als Java und auf dem alten Nexus One etwas langsamer ist. Wenn jemand diese Tests auch ausführen möchte, lass es mich wissen und ich werde die Quellen auf GitHub aktualisieren. Es wäre besonders interessant, Ergebnisse von einem echten Android-Gerät mit Intel-Prozessor zu sehen.
Update 26.07.2013
Nur ein kurzes Update, das von Benchmark-Apps mit dem neuesten Xamarin.Android 4.8 und dem heute veröffentlichten Update dot42 1.0.1.72 neu kompiliert wurde - keine wesentlichen Änderungen gegenüber den zuvor gemeldeten Ergebnissen.
Update 30.07.2013 - bessere Ergebnisse für dot42
Dot42 wurde erneut mit Roberts (von Dot42-Herstellern) Port meines Java-Codes auf C # getestet. In meinem C # -Port, der ursprünglich für Xamarin erstellt wurde, habe ich einige native Java-Klassen wie ListArray durch eine für C # native List-Klasse usw. ersetzt. Robert hatte meinen Dot42-Quellcode nicht, portierte ihn daher erneut aus Java und verwendete die ursprünglichen Java-Klassen in Solche Orte, von denen Dot42 profitiert, werden vermutlich in Dalvik VM wie Java und nicht in Mono wie Xamarin ausgeführt. Jetzt sind die Dot42-Ergebnisse viel besser. Hier ist ein Protokoll von meinen Tests:
30.07.2013 - Dot42 testet mit mehr Java-Klassen in Dot42 C #
Intel Emulator, Android 4.2
Dot42, Gregs Code mit StringBuilder.Replace () (wie in Xamarin):
Gesamtsumme (5 Läufe): 3646 ms, mit einer Lesesumme von 3830 msDot42, Gregs Code mit String.Replace () (wie in Java und Roberts Code):
Gesamtsumme (5 Läufe): 3027 ms, mit einer Lesesumme von 3206 msDot42, Roberts Code:
Gesamtsumme (5 Läufe): 1781 ms, mit Gesamtlesung der Datei: 1999 msXamarin:
Gesamtsumme (5 Läufe): 1373 ms, mit einer Gesamtlesezeit von 1505 msJava:
Gesamtsumme der Zeit (5 Läufe): 1841 ms, mit einer Gesamtlesezeit von 2044 msARM, Samsung Galaxy Note 2, Stromsparmodus, Android 4.1.1
Dot42, Gregs Code mit StringBuilder.Replace () (wie in Xamarin):
Gesamtsumme (5 Läufe): 10875 ms, mit gelesener Datei insgesamt: 11280 msDot42, Gregs Code mit String.Replace () (wie in Java und Roberts Code):
Gesamtsumme (5 Läufe): 9710 ms, mit einer Lesesumme von 10097 msDot42, Roberts Code:
Gesamtsumme (5 Läufe): 6279 ms, mit einer Lesesumme von 6622 msXamarin:
Gesamtsumme (5 Läufe): 6201 ms, mit einer Gesamtlesezeit von 6476 msJava:
Gesamtsumme (5 Läufe): 7141 ms, mit einer Lesesumme von 7479 ms
Ich denke immer noch, dass Dot42 noch einen langen Weg vor sich hat. Java-ähnliche Klassen (z. B. ArrayList) und eine gute Leistung mit ihnen würden die Portierung von Code von Java nach C # etwas vereinfachen. Dies ist jedoch etwas, was ich wahrscheinlich nicht viel tun würde. Ich möchte lieber vorhandenen C # -Code (Bibliotheken usw.) verwenden, der native C # -Klassen (z. B. List) verwendet und der mit dem aktuellen dot42-Code langsam und mit Xamarin sehr gut funktioniert.
Greg