c# - market - xamarin vs react native




Gibt es Benchmarks(Code und Ergebnisse), die die Leistung von Android-Apps in Xamarin C#und Java vergleichen? (5)

Performance

Leistung ist ein vages Wort, wenn Sie nicht definieren, was Sie unter Leistung verstehen. Wenn es eine einfache Rechenleistung ist, kann Xamarin je nach Art der Berechnung schneller als Java sein.

Android kommt nativ mit Multiple-Forms zum Ausführen von Code in:

  • RenderScript (CPU und GPU)
  • Java (SDK)
  • C ++ (NDK)
  • OpenGL (GPU)

Es ist ziemlich offensichtlich, dass wenn Code ausgeführt wird, je nativer die Lösung ist, desto schneller wird es sein. Eine laufzeitbasierte Sprache wird niemals eine Sprache schlagen, die direkt auf der CPU läuft.

Auf der anderen Seite, wenn Sie die tatsächliche Nutzungsleistung messen wollen, wird Java schneller als Xamarin.

Xamarin und warum es langsamer sein kann

Wenn Xamarin mit einfachen alten Java-Anwendungen verglichen wird, kann die Leistung für Xamarin sehr viel schneller sein, da es langsamer sein kann.

In einem realen Beispiel sind Xamarin-Anwendungen sehr wahrscheinlich langsamer als Java-Anwendungen, da viele Android- / Java- (System-) Aufrufe mithilfe sogenannter Bindungen an die Xamarin-Laufzeit delegiert werden müssen.

Es gibt ein paar verschiedene Arten von Bindungen, die wichtig sind zu wissen:

  • JNI (Java Native Interface): Die Bindung, die in vielen Android-Anwendungen als Schnittstelle zwischen Java-Code (SDK) und nativem C ++ - Code (NDK) verwendet wird.
  • MCW (Managed Callable Wrappers): Eine Bindung, die in Xamarin für die Schnittstelle von verwaltetem C # -Code zu Java-Code (Android-Laufzeit) verfügbar ist.
  • ACW (Android Callable Wrappers): Eine Bindung, die in Xamarin für die Schnittstelle von Java-Code (Android-Laufzeit) zu verwaltetem C # -Code verfügbar ist.

Mehr zu MCW und ACW finden Sie hier: https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/

Bindungen sind hinsichtlich der Leistung sehr sehr kostenintensiv. Das Aufrufen einer C ++ - Methode aus Java fügt einen enormen Aufwand beim Aufrufen von Zeit hinzu. Das Aufrufen einer C ++ - Methode aus C ++ ist viele, viele Male schneller.

Jemand hat einen Leistungstest durchgeführt, um zu berechnen, wie viele Java-Vorgänge im Durchschnitt ein JNI-Anruf kostet: Wie hoch ist der quantitative Aufwand für einen JNI-Anruf?

Aber nicht nur JNI-Anrufe sind teuer, sondern auch Anrufe von und nach MCW und ACW. Real-World-Xamarin-Anwendungen machen viele Aufrufe mit Bindings und aus diesem Grund kann die tatsächliche Verwendung einer Xamarin-Anwendung langsamer als eine einfache alte Java-Anwendung sein (und wird dies im Allgemeinen sein). Je nachdem, wie die Xamarin-Anwendung entwickelt wurde, ist es sehr wahrscheinlich, dass der Benutzer den Unterschied nicht bemerkt.

TLDR / Fazit: Xamarin muss al-Sortierungen verwenden, die zeitaufwendig sind.

Neben Bindungen spielen noch viele andere Faktoren eine Rolle, wenn es um reale Leistung geht, zum Beispiel: Größe der Binärdatei, Laden der App im Speicher, I / O-Operationen und vieles mehr. Ein Blogbeitrag, der einige dieser Dinge untersucht, finden Sie hier: https://magenic.com/thinking/mobile-development-platform-performance-part-2-native-cordova-classic-xamarin-xamarin-forms

Ich stieß auf Xamarin behauptet, dass ihre Mono-Implementierung auf Android und ihre C # kompilierten Anwendungen schneller als Java-Code sind. Hat jemand auf sehr unterschiedlichen Android-Plattformen tatsächliche Benchmarks mit sehr ähnlichem Java- und C # -Code durchgeführt, um solche Behauptungen zu überprüfen, könnte er den Code und die Ergebnisse veröffentlichen?

Hinzugefügt am 18. Juni 2013

Da es keine Antwort gab und diese Benchmarks von anderen nicht gefunden werden konnten, entschied ich mich, meine eigenen Tests durchzuführen. Leider bleibt meine Frage "gesperrt", so dass ich diese nicht als Antwort posten kann, nur die Frage bearbeiten. Bitte stimme ab, diese Frage erneut zu beantworten. Für C # habe ich Xamarin.Android ver. 4.7.09001 (Beta). Der Quellcode, alle Daten, die ich zum Testen verwendet habe, und kompilierte APK-Pakete sind 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 auch daran interessiert, die Ergebnisse zu erfahren.

Ergebnisse meiner Tests

Ich habe meine Satz-Extraktor-Klasse nach C # portiert (von 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 und die Gesamtzeit für 3 verschiedene Geräte und einen Emulator sind unten aufgeführt. Ich habe "Release" Builds nur getestet, ohne Debugging aktiviert.

HTC Nexus One Android 2.3.7 (API 10) - CyanogenMod ROM

Java: Großartige Gesamtzeit (5 Durchläufe): 12361 ms, mit gelesener Dateisumme: 13304 ms

C #: Gesamtzeit (5 Läufe): 17504 ms, mit gelesener Dateisumme: 17956 ms

Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM

Java: Gesamtzeit (5 Läufe): 8947 ms, mit gelesener Dateisumme: 9186 ms

C #: Gesamtzeit (5 Läufe): 9884 ms, mit insgesamt gelesener Datei: 10247 ms

Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM

Java: Gesamtzeit (5 Läufe): 9742 ms, mit gelesener Dateisumme: 10111 ms

C #: Gesamtzeit (5 Läufe): 10459 ms, mit insgesamt gelesener Datei: 10696 ms

Emulator - Intel (Android 4.2, API 17)

Java: Gesamtzeit (5 Läufe): 2699 ms, mit gelesener Dateisumme: 3127 ms

C #: Gesamtzeit (5 Läufe): 2049 ms, mit gelesener Dateisumme: 2182 ms

Emulator - Intel (Android 2.3.7, API 10)

Java: Gesamtzeit (5 Läufe): 2992 ms, mit gelesener Dateisumme: 3591 ms

C #: Gesamtzeit (5 Läufe): 2049 ms, mit gelesenen Dateien insgesamt: 2257 ms

Emulator - Arm (Android 4.0.4, API 15)

Java: Großartige Gesamtzeit (5 Läufe): 41751 ms, mit insgesamt gelesener Datei: 43866 ms

C #: Gesamtzeit (5 Läufe): 44136 ms, mit gelesener Dateisumme: 45109 ms

Kurze Diskussion

Mein Testcode enthält hauptsächlich Textanalyse-, Ersetzen- und Regex-Suchen, möglicherweise für anderen Code (z. B. mehr numerische Operationen) würden die Ergebnisse unterschiedlich sein. Auf allen Geräten mit ARM-Prozessoren schnitt Java besser ab als Xamarin C # -Code. Der größte Unterschied war unter Android 2.3, wo C # -Code bei ca. 70% der Java-Geschwindigkeit.

Auf Intel-Emulator (mit Intel HAX-Technologie, Emulator läuft im schnellen Virt-Modus), Xamarin C # -Code führt meinen Beispielcode viel schneller als Java - etwa 1,35 mal schneller. Vielleicht sind Mono Virtual Machine Code und Bibliotheken auf Intel viel besser optimiert als auf ARM?

Bearbeiten Sie den 8. Juli 2013

Ich habe gerade den Genymotion Android Emulator installiert, der in Oracle VirtualBox läuft, und wieder benutzt dieser 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: Großartige Gesamtzeit (5 Läufe): 2069 ms, mit insgesamt gelesener Datei: 2248 ms

C #: Gesamtzeit (5 Läufe): 1543 ms, mit gelesener Dateisumme: 1642 ms

Ich habe dann festgestellt, dass es ein Update für Xamarin.Android beta, Version 4.7.11, gibt, mit Versionshinweisen, die auch einige Änderungen in der Mono-Laufzeit erwähnen. Beschlossen, einige ARM-Geräte schnell zu testen, und große Überraschung - C # -Zahlen verbessert:

BN Nook XD +, ARM (Android 4.0)

Java: Gesamtzeit (5 Läufe): 8103 ms, mit insgesamt gelesener Datei: 8569 ms

C #: Gesamtzeit (5 Läufe): 7951 ms, mit gelesener Dateisumme: 8161 ms

Beeindruckend! C # ist jetzt besser als Java? Ich habe beschlossen, den Test auf meinem Galaxy Note 2 zu wiederholen:

Samsung Galaxy Note 2 - ARM (Android 4.1.1)

Java: Gesamtzeit (5 Läufe): 9675 ms, mit gelesener Dateisumme: 10028 ms

C #: Gesamtzeit (5 Läufe): 9911 ms, mit gelesener Dateisumme: 10104 ms

Hier scheint C # nur etwas 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. Auf Nook wurde es deaktiviert, auf Note 2 - aktiviert. Entschied sich zu testen, dass der Energiesparmodus deaktiviert ist (wie bei aktiviert, begrenzt es auch die Prozessorgeschwindigkeit):

Samsung Galaxy Note 2 - ARM (Android 4.1.1), Energiesparmodus deaktiviert

Java: Gesamtzeit (5 Läufe): 7153 ms, mit gelesenen Dateien insgesamt: 7459 ms

C #: Gesamtzeit (5 Läufe): 6906 ms, mit gelesener Dateisumme: 7070 ms

Jetzt ist C # überraschenderweise etwas schneller als Java auf dem ARM-Prozessor. Großer Fortschritt!

Bearbeiten Sie 12. Juli 2013

Wir alle wissen, dass nichts den nativen Code für Geschwindigkeit übertrifft, und ich war nicht mit der Leistung meines Satzteilers in Java oder C # zufrieden, besonders, dass ich es verbessern muss (und es dadurch noch langsamer machen muss). Beschlossen, es in C ++ neu zu schreiben. Hier ist eine kleine (dh eine kleinere Anzahl von Dateien als frühere Tests, aus anderen Gründen) Vergleich der Geschwindigkeit von nativen vs Java auf meinem Galaxy Note 2, mit Energiesparmodus deaktiviert:

Java: Gesamtzeit (5 Läufe): 3292 ms, mit gelesener Dateisumme: 3454 ms

Nativer Daumen: Gesamtzeit (5 Läufe): 537 ms, mit insgesamt gelesener Datei: 657 ms

Nativer Arm: Gesamtzeit (5 Läufe): 458 ms, Gesamtlänge der Datei: 587 ms

Für meinen speziellen Test ist der native Code 6 bis 7 mal schneller als Java. Vorbehalt: Ich konnte die std :: regex-Klasse nicht auf Android verwenden, also musste ich meine eigenen spezialisierten Routinen schreiben, die nach Absatzumbrüchen oder HTML-Tags suchen. Meine anfänglichen Tests des gleichen Codes auf einem PC mit Regex, waren etwa 4 bis 5 mal schneller als Java.

Puh! Wenn ich den rohen Speicher mit char * oder wchar * Zeigern wieder aufweckte, fühlte ich mich sofort 20 Jahre jünger! :)

Bearbeiten Sie den 15. Juli 2013

(Siehe unten, mit Änderungen vom 30.07.2013, für viel bessere Ergebnisse mit Dot42)

Mit einigen Schwierigkeiten habe ich meine C # -Tests auf Dot42 (Version 1.0.1.71 Beta) portiert, eine weitere C # -Plattform für Android. Vorläufige Ergebnisse zeigen, dass der Dot42-Code auf einem Intel-Android-Emulator etwa dreimal (3-mal) langsamer ist als Xamarin C # (Version 4.7.11). Ein Problem ist, dass die System.Text.RegularExpressions-Klasse in Dot42 nicht über die Funktion Split () verfügt, die ich in Xamarin-Tests verwendet habe. Daher habe ich die Klasse Java.Util.Regex und Java.Util.Regex.Pattern.Split ( ), an diesem bestimmten Ort im Code gibt es diesen kleinen Unterschied. Sollte jedoch kein großes Problem sein. Dot42 kompiliert zu Dalvik (DEX) Code, so dass es nativ mit Java mit Android kooperiert, braucht kein teures Interop von C # nach Java wie Xamarin.

Zum Vergleich, ich habe den Test auch auf ARM-Geräten durchgeführt - hier ist der Dot42-Code "nur" 2x langsamer als Xamarin C #. Hier sind meine Ergebnisse:

HTC Nexus One Android 2.3.7 (ARM)

Java: Gesamtzeit (5 Läufe): 12187 ms, mit gelesener Dateisumme: 13200 ms

Xamarin C #: Gesamtzeit (5 Läufe): 13935 ms, mit insgesamt gelesener Datei: 14465 ms

Dot42 C #: Gesamtzeit (5 Läufe): 26000 ms, mit gelesener Dateisumme: 27168 ms

Samsung Galaxy Note 2, Android 4.1.1 (ARM)

Java: Großartige Gesamtzeit (5 Durchläufe): 6895 ms, mit gelesener Dateigesamtlänge: 7275 ms

Xamarin C #: Gesamtzeit (5 Läufe): 6466 ms, mit insgesamt gelesener Datei: 6720 ms

Dot42 C #: Gesamtzeit (5 Läufe): 11185 ms, mit gelesener Dateisumme: 11843 ms

Intel Emulator, Android 4.2 (x86)

Java: Gesamtzeit (5 Läufe): 2389 ms, mit gelesener Dateisumme: 2770 ms

Xamarin C #: Gesamtzeit (5 Läufe): 1748 ms, mit gelesener Datei: 1933 ms

Dot42 C #: Gesamtzeit (5 Läufe): 5150 ms, mit gelesener Datei: 5459 ms

Für mich war es auch interessant festzustellen, dass Xamarin C # auf einem neueren ARM-Gerät etwas schneller ist als Java und auf dem alten Nexus One etwas langsamer. Wenn jemand diese Tests auch durchfü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 7/26/2013

Nur ein kurzes Update, neu kompiliert von Benchmark-Apps mit dem neuesten Xamarin.Android 4.8, und auch mit dem Update von dot42 1.0.1.72, das heute veröffentlicht wurde - keine wesentlichen Änderungen gegenüber den zuvor gemeldeten Ergebnissen.

Update 30.07.2013 - bessere Ergebnisse für dot42

Habe Dot42 mit Roberts (von dot42 makers) Port meines Java-Codes auf C # getestet. In meinem C # -Port, der ursprünglich für Xamarin erstellt wurde, ersetzte ich einige native Java-Klassen wie ListArray durch die in C # enthaltene List-Klasse. Robert hatte meinen Dot42-Quellcode nicht, also portierte er ihn erneut aus Java und verwendete ursprüngliche Java-Klassen in solche Orte, die Dot42 nutzen, schätze ich, weil es in Dalvik VM läuft, wie Java, und nicht in Mono, wie Xamarin. Jetzt sind die Dot42-Ergebnisse viel besser. Hier ist ein Protokoll von meinem Test:

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):
Gesamtzeit (5 Läufe): 3646 ms, mit gelesener Dateisumme: 3830 ms

Dot42, Gregs Code mit String.Replace () (wie in Java und Roberts Code):
Gesamtzeit (5 Läufe): 3027 ms, mit gelesener Datei: 3206 ms

Dot42, Roberts Code:
Gesamtzeit (5 Läufe): 1781 ms, mit gelesener Datei gesamt: 1999 ms

Xamarin:
Gesamtzeit (5 Läufe): 1373 ms, mit gelesener Dateisumme: 1505 ms

Java:
Grand Gesamtzeit (5 Läufe): 1841 ms, mit Datei lesen insgesamt: 2044 ms

ARM, Samsung Galaxy Note 2, Energiesparmodus, Android 4.1.1

Dot42, Gregs Code mit StringBuilder.Replace () (wie in Xamarin):
Gesamtzeit (5 Läufe): 10875 ms, mit gelesener Dateisumme: 11280 ms

Dot42, Gregs Code mit String.Replace () (wie in Java und Roberts Code):
Gesamtzeit (5 Läufe): 9710 ms, mit gelesener Dateisumme: 10097 ms

Dot42, Roberts Code:
Gesamtzeit (5 Läufe): 6279 ms, mit gelesener Dateisumme: 6622 ms

Xamarin:
Grand Gesamtzeit (5 Läufe): 6201 ms, mit Datei lesen insgesamt: 6476 ms

Java:
Gesamtzeit (5 Läufe): 7141 ms, mit gelesener Dateisumme: 7479 ms

Ich denke immer noch, dass Dot42 noch einen langen Weg vor sich hat. Java-ähnliche Klassen (zB ArrayList) und eine gute Performance mit ihnen zu haben, würde die Portierung von Code von Java nach C # etwas einfacher machen. Aber das würde ich wahrscheinlich nicht viel tun. Ich würde lieber den vorhandenen C # -Code (Bibliotheken usw.) verwenden wollen, der native C # -Klassen (zB List) verwenden wird und der mit dem aktuellen dot42-Code und sehr gut mit Xamarin langsam arbeiten würde.

Greg


Es sind ziemlich alte Tests, die aber relevant sein könnten: https://github.com/EgorBo/Xamarin.Android-vs-Java

Arithmetischer Test

Sammlungen, Generika, benutzerdefinierte Werttypen

Mit Strings arbeiten

UPD: neue Daten mit Google Pixel 2 (Danke yousha-aleayoub )


Ja, Xamarins Mono Virtual Machine ist beeindruckender als Googles Dalvik in Android. Ich habe es mit HTC Flyer und Acer Iconia Tab Tablets getestet, um den C # -Port von Android über Mono gegen Java Dalvik zu bewerten, wobei die C # -Implementierung von Android den Java-basierten Dalvik gut übertrifft.


Wir haben kürzlich mit Xamarin nach einer App gesucht. Wir verwendeten den C # -Code, den wir bereits für die Windows RT-Version unserer App geschrieben hatten. Einige spezifische Details mussten für die Android-Version neu geschrieben werden.

Was wir entdeckt haben ist, dass I / O in Xamarin C # etwa 2x langsamer als Java ist. Unsere App ist stark I / O-gebunden. Wir haben die Ursache dafür noch nicht entdeckt, aber im Moment nehmen wir an, dass es auf Marshalling zurückzuführen ist. Während wir versuchen, die meiste Zeit in der Mono VM zu bleiben, wissen wir nicht, wie Mono tatsächlich auf die Festplatte zugreift.

Es besagt auch, dass unser C # -Code SQLite.NET verwendet ( https://github.com/praeclarum/sqlite-net ). Identische Fetches, die den SQLite.NET-Code verwenden, sind ebenfalls 2x langsamer als der Java SQLite-Wrapper von Android. Nach dem Betrachten des Quellcodes scheint er direkt an die C-DLL gebunden zu sein, also weiß ich nicht, warum es so viel langsamer ist. Eine Möglichkeit besteht darin, dass das Marshalling von Zeichenketten von nativ zu Java unter Android schneller sein kann als zu C # auf Xamarin.






dot42