566 votes

Quelqu'un dispose-t-il de benchmarks (code et résultats) comparant les performances d'applications Android écrites en C# et Java de Xamarin ?

Je suis tombé sur les affirmations de Xamarin selon lesquelles leur implémentation Mono sur Android et leurs applications compilées en C# sont plus rapides que le code Java. Est-ce que quelqu'un a effectué des benchmarks réels sur des codes Java et C# très similaires sur différentes plateformes Android pour vérifier ces affirmations, et a pu poster le code et les résultats ?

Ajouté le 18 juin 2013

Comme il n'y avait pas de réponse et que je n'ai pas pu trouver de tels benchmarks réalisés par d'autres, j'ai décidé de faire mes propres tests. Malheureusement, ma question reste "verrouillée" et je ne peux donc pas publier cette réponse, mais seulement modifier la question. Veuillez voter pour la réouverture de cette question. Pour C#, j'ai utilisé Xamarin.Android ver. 4.7.09001 (beta). Le code source, toutes les données que j'ai utilisées pour les tests, et les paquets APK compilés sont sur GitHub :

Java : https://github.com/gregko/TtsSetup_Java

C# : https://github.com/gregko/TtsSetup_C_sharp

Si quelqu'un souhaite répéter mes tests sur d'autres appareils ou émulateurs, je serais intéressé de connaître les résultats également.

Résultats de mes tests

J'ai porté ma classe d'extracteur de phrases en C# (à partir de mon application @Voice Aloud Reader) et j'ai effectué quelques tests sur 10 fichiers html en anglais, russe, français, polonais et tchèque. Chaque test a été effectué 5 fois sur les 10 fichiers, et le temps total pour 3 appareils différents et un émulateur est affiché ci-dessous. J'ai testé les versions "Release" uniquement, sans débogage activé.

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

Java : Temps total (5 exécutions) : 12361 ms, avec un total de lecture de fichier : 13304 ms

C# : Temps total (5 exécutions) : 17504 ms, avec un total de lecture de fichier : 17956 ms

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

Java : Temps total (5 exécutions) : 8947 ms, avec un total de lecture de fichier : 9186 ms

C# : Temps total (5 exécutions) : 9884 ms, avec un total de 10247 ms pour la lecture du fichier.

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

Java : Temps total (5 exécutions) : 9742 ms, avec un total de lecture de fichier : 10111 ms

C# : Temps total (5 exécutions) : 10459 ms, avec un total de lecture de fichier : 10696 ms

Emulateur - Intel (Android 4.2, API 17)

Java : Temps total (5 exécutions) : 2699 ms, avec un total de 3127 ms pour la lecture du fichier.

C# : Temps total (5 exécutions) : 2049 ms, avec un total de 2182 ms pour la lecture du fichier.

Emulateur - Intel (Android 2.3.7, API 10)

Java : Temps total (5 exécutions) : 2992 ms, avec un total de lecture de fichier : 3591 ms

C# : Temps total (5 exécutions) : 2049 ms, avec lecture du fichier total : 2257 ms

Emulateur - Arm (Android 4.0.4, API 15)

Java : Temps total (5 exécutions) : 41751 ms, avec un total de 43866 ms pour la lecture du fichier.

C# : Temps total (5 exécutions) : 44136 ms, avec un total de lecture de fichier : 45109 ms

Brève discussion

Mon code de test contient principalement des analyses de texte, des remplacements et des recherches Regex, peut-être que pour d'autres codes (par exemple, plus d'opérations numériques), les résultats seraient différents. Sur tous les appareils dotés de processeurs ARM, Java a donné de meilleurs résultats que le code C# de Xamarin. La plus grande différence a été constatée sous Android 2.3, où le code C# s'est exécuté à environ 70 % de la vitesse de Java.

Sur un émulateur Intel (avec la technologie Intel HAX, l'émulateur fonctionne en mode virtuel rapide), le code C# de Xamarin exécute mon code d'exemple beaucoup plus rapidement que Java - environ 1,35 fois plus vite. Peut-être que le code et les bibliothèques de la machine virtuelle Mono sont bien mieux optimisés sur Intel que sur ARM ?

Editer le 8 juillet 2013

Je viens d'installer l'émulateur Android Genymotion, qui fonctionne dans Oracle VirtualBox, et encore une fois celui-ci utilise le processeur Intel natif, pas l'émulation du processeur ARM. Comme avec l'émulateur Intel HAX, C# s'exécute ici aussi beaucoup plus rapidement. Voici mes résultats :

Émulateur Genymotion - Intel (Android 4.1.1, API 16)

Java : Temps total (5 exécutions) : 2069 ms, avec un total de lecture de fichier : 2248 ms

C# : Temps total (5 exécutions) : 1543 ms, avec un total de lecture de fichier : 1642 ms

J'ai ensuite remarqué qu'il y avait une mise à jour de la version bêta de Xamarin.Android, la version 4.7.11, avec des notes de publication mentionnant certains changements dans le runtime Mono également. J'ai décidé de tester rapidement quelques appareils ARM, et grosse surprise : les chiffres de C# se sont améliorés :

BN Nook XD+, ARM (Android 4.0)

Java : Temps total (5 exécutions) : 8103 ms, avec un total de 8569 ms pour la lecture du fichier.

C# : Temps total (5 exécutions) : 7951 ms, avec un total de lecture de fichier : 8161 ms

Wow ! C# est maintenant meilleur que Java ? J'ai décidé de répéter le test sur mon Galaxy Note 2 :

Samsung Galaxy Note 2 - ARM (Android 4.1.1)

Java : Temps total (5 exécutions) : 9675 ms, avec un total de lecture de fichier : 10028 ms

C# : Temps total (5 exécutions) : 9911 ms, avec lecture du fichier total : 10104 ms

Ici, le C# ne semble être que légèrement plus lent, mais ces chiffres m'ont fait réfléchir : Pourquoi le temps est plus long que sur le Nook HD+, même si le Note 2 a un processeur plus rapide ? La réponse : le mode économie d'énergie. Sur le Nook, il était désactivé, sur le Note 2 - activé. J'ai décidé de tester avec le mode d'économie d'énergie désactivé (comme s'il était activé, il limite également la vitesse du processeur) :

Samsung Galaxy Note 2 - ARM (Android 4.1.1), économie d'énergie désactivée

Java : Temps total (5 exécutions) : 7153 ms, avec un total de lecture de fichier : 7459 ms

C# : Temps total (5 exécutions) : 6906 ms, avec un total de 7070 ms pour la lecture du fichier.

Maintenant, étonnamment, C# est légèrement plus rapide que Java sur un processeur ARM également. Une grande amélioration !

Editer le 12 juillet 2013

Nous savons tous que rien ne vaut le code natif pour la vitesse, et je n'étais pas satisfait des performances de mon séparateur de phrases en Java ou C#, en particulier que je dois l'améliorer (et donc le rendre encore plus lent). J'ai décidé de le réécrire en C++. Voici une petite comparaison (c'est-à-dire un ensemble de fichiers plus petit que les tests précédents, pour d'autres raisons) de la vitesse du langage natif par rapport à Java sur mon Galaxy Note 2, avec le mode économie d'énergie désactivé :

Java : Temps total (5 exécutions) : 3292 ms, avec un total de lecture de fichier : 3454 ms

Pouce natif : Temps total (5 exécutions) : 537 ms, avec lecture du fichier total : 657 ms

Bras natif : Temps total (5 exécutions) : 458 ms, avec lecture de fichier total : 587 ms

Il semble que pour mon test particulier, le code natif soit 6 à 7 fois plus rapide que Java. Mise en garde : je n'ai pas pu utiliser la classe std::regex sur Android, j'ai donc dû écrire mes propres routines spécialisées pour rechercher les sauts de paragraphes ou les balises html. Mes premiers tests du même code sur un PC en utilisant regex, étaient environ 4 à 5 fois plus rapides que Java.

Ouf ! En réveillant à nouveau la mémoire brute avec des pointeurs char* ou wchar*, je me suis instantanément senti rajeuni de 20 ans ! :)

Editer le 15 juillet 2013

(Voir ci-dessous, avec les modifications du 30/07/2013, pour de bien meilleurs résultats avec Dot42)

Avec quelques difficultés, j'ai réussi à porter mes tests C# vers Dot42 (version 1.0.1.71 beta), une autre plateforme C# pour Android. Les résultats préliminaires montrent que le code Dot42 est environ 3x (3 fois) plus lent que Xamarin C# (v. 4.7.11), sur un émulateur Intel Android. Un problème est que la classe System.Text.RegularExpressions dans Dot42 n'a pas la fonction Split() que j'ai utilisée dans les tests Xamarin, donc j'ai utilisé la classe Java.Util.Regex à la place, et Java.Util.Regex.Pattern.Split(), donc à cet endroit particulier du code il y a cette petite différence. Cela ne devrait pas être un gros problème. Dot42 compile en code Dalvik (DEX), donc il coopère avec Java sur Android de manière native, il n'a pas besoin d'une interopération coûteuse de C# à Java comme Xamarin.

À titre de comparaison, j'ai également effectué le test sur des appareils ARM - ici, le code Dot42 est "seulement" 2 fois plus lent que le C# de Xamarin. Voici mes résultats :

HTC Nexus One Android 2.3.7 (ARM)

Java : Temps total (5 exécutions) : 12187 ms, avec un total de lecture de fichier : 13200 ms

Xamarin C# : Temps total (5 exécutions) : 13935 ms, avec un total de lecture de fichier : 14465 ms

Dot42 C# : Temps total (5 exécutions) : 26000 ms, avec lecture du fichier total : 27168 ms

Samsung Galaxy Note 2, Android 4.1.1 (ARM)

Java : Temps total (5 exécutions) : 6895 ms, avec un total de 7275 ms pour la lecture du fichier.

Xamarin C# : Temps total (5 exécutions) : 6466 ms, avec un total de 6720 ms pour la lecture du fichier.

Dot42 C# : Temps total (5 exécutions) : 11185 ms, avec un total de lecture de fichier : 11843 ms

Émulateur Intel, Android 4.2 (x86)

Java : Temps total (5 exécutions) : 2389 ms, avec un total de 2770 ms pour la lecture du fichier.

Xamarin C# : Temps total (5 exécutions) : 1748 ms, avec un total de lecture de fichier : 1933 ms

Dot42 C# : Temps total (5 exécutions) : 5150 ms, avec un total de 5459 ms pour la lecture du fichier.

Il était également intéressant de noter que Xamarin C# est légèrement plus rapide que Java sur un appareil ARM récent, et légèrement plus lent sur le vieux Nexus One. Si quelqu'un souhaite également effectuer ces tests, faites-le moi savoir et je mettrai à jour les sources sur GitHub. Il serait particulièrement intéressant de voir les résultats sur un vrai appareil Android avec un processeur Intel.

Mise à jour 7/26/2013

Juste une mise à jour rapide, recompilé par des applications de référence avec la dernière Xamarin.Android 4.8, et aussi avec la mise à jour dot42 1.0.1.72 publiée aujourd'hui - pas de changements significatifs par rapport aux résultats rapportés auparavant.

Mise à jour 7/30/2013 - meilleurs résultats pour dot42

J'ai re-testé Dot42 avec le portage par Robert (de dot42 makers) de mon code Java vers C#. Dans mon portage C# réalisé initialement pour Xamarin, j'ai remplacé certaines classes Java natives, comme ListArray, par la classe List native de C#, etc. Robert n'avait pas mon code source Dot42, il l'a donc porté à nouveau à partir de Java et a utilisé les classes Java originales à ces endroits, ce qui profite à Dot42, je suppose parce qu'il fonctionne dans Dalvik VM, comme Java, et non dans Mono, comme Xamarin. Maintenant, les résultats de Dot42 sont bien meilleurs. Voici un journal de mes tests :

30/07/2013 - Les tests de Dot42 avec plus de classes Java dans Dot42 C#

Émulateur Intel, Android 4.2

Dot42, le code de Greg utilise StringBuilder.Replace() (comme dans Xamarin) :
Temps total (5 exécutions) : 3646 ms, avec un total de 3830 ms pour la lecture du fichier.

Dot42, le code de Greg utilise String.Replace() (comme dans le code de Java et de Robert) :
Temps total (5 exécutions) : 3027 ms, avec un total de 3206 ms pour la lecture du fichier.

Dot42, Code Robert :
Temps total (5 exécutions) : 1781 ms, avec un total de lecture de fichier : 1999 ms

Xamarin :
Temps total (5 exécutions) : 1373 ms, avec un total de 1505 ms pour la lecture du fichier.

Java :
Temps total (5 exécutions) : 1841 ms, avec un total de 2044 ms pour la lecture du fichier.

ARM, Samsung Galaxy Note 2, économie d'énergie désactivée, Android 4.1.1

Dot42, le code de Greg utilise StringBuilder.Replace() (comme dans Xamarin) :
Temps total (5 exécutions) : 10875 ms, avec un total de 11280 ms pour la lecture du fichier.

Dot42, le code de Greg utilise String.Replace() (comme dans le code de Java et de Robert) :
Temps total (5 exécutions) : 9710 ms, avec un total de lecture de fichier : 10097 ms

Dot42, Code Robert :
Temps total (5 exécutions) : 6279 ms, avec un total de 6622 ms pour la lecture du fichier.

Xamarin :
Temps total (5 exécutions) : 6201 ms, avec un total de 6476 ms pour la lecture du fichier.

Java :
Temps total (5 exécutions) : 7141 ms, avec un total de 7479 ms pour la lecture du fichier.

Je pense toujours que Dot42 a un long chemin à parcourir. Le fait d'avoir des classes semblables à celles de Java (par exemple ArrayList) et une bonne performance avec elles, rendrait le portage de code de Java à C# légèrement plus facile. Cependant, c'est quelque chose que je ne ferais probablement pas souvent. Je préférerais utiliser du code C# existant (bibliothèques, etc.), qui utilisera des classes C# natives (par exemple List), et qui fonctionnera lentement avec le code actuel dot42, et très bien avec Xamarin.

Greg

5 votes

Mode DEBUG sur Nexus 7 4.2.2 avec quelques optimisations sur les chaînes de caractères et xamarin alpha 9 : Temps total : 3907 ms, avec un total de lecture de fichiers : 4016. Que signifie "5 runs" ?

0 votes

Mode Release sur la même plateforme : Temps total : 2192 ms, avec un total de lecture de fichiers : 2279

0 votes

Mais votre code peut être optimisé bien davantage.

8voto

Rolf Smit Points 1678

Performance

Les performances sont un mot vague si vous ne définissez pas ce que vous entendez par performances. S'il s'agit de simples performances de calcul, Xamarin peut être plus rapide que Java en fonction de la nature du calcul.

Android propose nativement plusieurs formulaires pour l'exécution du code :

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

Il est tout à fait évident que lors de l'exécution d'un code, plus la solution est native, plus elle sera rapide. Un langage basé sur l'exécution ne battra jamais un langage qui s'exécute directement sur le CPU.

Mais d'un autre côté, si vous voulez mesurer la performance de l'utilisation réelle, Java sera probablement plus rapide que Xamarin.

Xamarin et pourquoi il peut être plus lent

Lorsque l'on compare Xamarin à de vieilles applications Java, les performances peuvent très bien être plus rapides pour Xamarin comme elles peuvent être plus lentes.

Dans un exemple concret, il est très probable que les applications Xamarin soient plus lentes que les applications Java, car de nombreux appels (système) Android/Java doivent être délégués vers et depuis le moteur d'exécution Xamarin à l'aide de ce que l'on appelle des liaisons.

Il y a quelques types de fixations différents qu'il est important de connaître :

  • JNI (Java Native Interface) : La liaison utilisée dans de nombreuses applications Android pour assurer l'interface entre le code Java (SDK) et le code C++ natif (NDK).
  • MCW (Managed Callable Wrappers) : Une liaison disponible dans Xamarin pour faire l'interface entre le code C# géré et le code Java (run-time Android).
  • ACW (Android Callable Wrappers) : Une liaison disponible dans Xamarin pour interfacer le code Java (run-time Android) avec le code C# géré.

Plus d'informations sur MCW et ACW ici : https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/

Les liaisons sont très coûteuses en termes de performances. L'appel d'une méthode C++ à partir de Java ajoute une énorme surcharge en temps d'appel, l'appel d'une méthode C++ à partir de C++ est beaucoup beaucoup beaucoup plus rapide.

Quelqu'un a fait un test de performance pour calculer le nombre d'opérations Java que coûte en moyenne un appel JNI : Quel est le surcoût quantitatif d'un appel JNI ?

Mais les appels JNI ne sont pas les seuls à être coûteux, tout comme les appels vers et depuis MCW et ACW. Les applications Xamarin réelles effectuent de nombreux appels à l'aide de liaisons et, de ce fait, l'utilisation réelle d'une application Xamarin peut être (et sera en général) plus lente qu'une vieille application Java ordinaire. Cependant, selon la façon dont l'application Xamarin a été conçue, il est très probable que l'utilisateur ne remarque même pas la différence.

TLDR/Conclusion : Xamarin doit utiliser toutes sortes de liaisons, ce qui est coûteux en temps.

Outre les liaisons, de nombreux autres facteurs entrent en jeu lorsqu'on parle de performances réelles, par exemple : la taille du binaire, le chargement de l'application en mémoire, les opérations d'E/S et bien d'autres encore. Un article de blog qui examine certains de ces éléments est disponible ici : https://magenic.com/thinking/mobile-development-platform-performance-part-2-native-cordova-classic-xamarin-xamarin-forms

4voto

Denis Gordin Points 626

Ce sont de vieux tests mais ils pourraient être pertinents : https://github.com/EgorBo/Xamarin.Android-vs-Java

Test d'arithmétique

enter image description here

Collections, génériques, types de valeurs personnalisées

enter image description here

Travailler avec des cordes

enter image description here

UPD : nouvelles données avec Google Pixel 2 (merci yousha-aleayoub )

Pixel 2 tests

1 votes

Mise à jour 2018 camo.githubusercontent.com/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X