Je suis tombé sur Xamarin qui prétend que leur implémentation Mono sur Android et leurs applications compilées en C # sont plus rapides que le code Java. Quelqu'un a-t-il effectué de véritables tests de performance sur du code Java et C # très similaire sur différentes plates-formes Android pour vérifier ces affirmations, pourrait-il publier le code et les résultats?
Publié le 18 juin 2013
Puisqu'il n'y avait pas de réponse et ne pouvait pas trouver de tels repères effectués par d'autres, j'ai décidé de faire mes propres tests. Malheureusement, ma question reste "verrouillée", je ne peux donc pas poster ceci comme réponse, seulement éditer la question. Veuillez voter pour rouvrir 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 tester et les packages 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 également intéressé d'apprendre les résultats.
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é des tests sur 10 fichiers HTML en anglais, russe, français, polonais et tchèque. Chaque exécution a été effectuée 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) - CyanogenMod ROM
Java: Grand total time (5 runs): 12361 ms, avec lecture du fichier total: 13304 ms
C #: Temps total total (5 exécutions): 17504 ms, avec total de lecture de fichiers: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - CyanogenMod ROM
Java: Grand total time (5 runs): 8947 ms, avec total de lecture de fichiers: 9186 ms
C #: Temps total total (5 exécutions): 9884 ms, avec total de lecture de fichiers: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - Samsung ROM
Java: Grand total time (5 runs): 9742 ms, avec total de lecture de fichiers: 10111 ms
C #: Temps total total (5 passages): 10459 ms, avec total de lecture de fichiers: 10696 ms
Émulateur - Intel (Android 4.2, API 17)
Java: Grand total time (5 runs): 2699 ms, avec lecture du fichier total: 3127 ms
C #: Temps total total (5 exécutions): 2049 ms, avec total de lecture de fichiers: 2182 ms
Émulateur - Intel (Android 2.3.7, API 10)
Java: Grand total time (5 runs): 2992 ms, avec lecture du fichier total: 3591 ms
C #: Temps total total (5 exécutions): 2049 ms, avec lecture totale du fichier: 2257 ms
Emulator - Arm (Android 4.0.4, API 15)
Java: Grand total time (5 runs): 41751 ms, avec lecture du fichier total: 43866 ms
C #: Temps total total (5 passages): 44136 ms, avec total de lecture de fichiers: 45109 ms
Brève discussion
Mon code de test contient principalement l'analyse de texte, le remplacement et les recherches Regex, peut-être pour un autre code (par exemple plus d'opérations numériques) les résultats seraient différents. Sur tous les appareils dotés de processeurs ARM, Java s'est comporté mieux que le code Xamarin C #. La plus grande différence était sous Android 2.3, où le code C # s'exécute à environ. 70% de la vitesse Java.
Sur l'émulateur Intel (avec la technologie Intel HAX, l'émulateur s'exécute en mode virt rapide), le code Xamarin C # exécute mon exemple de code beaucoup plus rapidement que Java - environ 1,35 fois plus rapidement. Peut-être que le code et les bibliothèques des machines virtuelles mono sont bien mieux optimisés sur Intel que sur ARM?
Modifier le 8 juillet 2013
Je viens d'installer l'émulateur Genymotion Android, qui s'exécute dans Oracle VirtualBox, et encore celui-ci utilise un processeur Intel natif, pas un processeur ARM émulant. Comme avec l'émulateur Intel HAX, C # s'exécute à nouveau ici beaucoup plus rapidement. Voici mes résultats:
Émulateur Genymotion - Intel (Android 4.1.1, API 16)
Java: Grand total time (5 runs): 2069 ms, avec lecture du fichier total: 2248 ms
C #: Temps total total (5 exécutions): 1543 ms, avec total de lecture de fichiers: 1642 ms
J'ai ensuite remarqué qu'il y avait une mise à jour de la version 4.7.11 de Xamarin.Android beta, avec des notes de publication mentionnant également certains changements dans l'exécution Mono. Décidé de tester rapidement certains appareils ARM, et grande surprise - les numéros C # ont été améliorés:
BN Nook XD +, ARM (Android 4.0)
Java: Grand total time (5 runs): 8103 ms, avec lecture du fichier total: 8569 ms
C #: Temps total total (5 exécutions): 7951 ms, avec un total de lecture de fichiers: 8161 ms
Hou la la! C # est maintenant meilleur que Java? Décidé de répéter le test sur mon Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: Grand total time (5 runs): 9675 ms, avec lecture du fichier total: 10028 ms
C #: Temps total total (5 exécutions): 9911 ms, avec total de lecture de fichiers: 10104 ms
Ici, C # semble être légèrement plus lent, mais ces chiffres m'ont donné une pause: pourquoi le temps est plus long que sur Nook HD +, même si Note 2 a un processeur plus rapide? La réponse: le mode d'économie d'énergie. Sur Nook, il était désactivé, sur Note 2 - activé. Décidé de tester avec le mode d'économie d'énergie désactivé (comme avec activé, cela limite également la vitesse du processeur):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), économie d'énergie désactivée
Java: Grand total time (5 runs): 7153 ms, avec lecture du fichier total: 7459 ms
C #: Temps total total (5 exécutions): 6906 ms, avec un total de lecture de fichiers: 7070 ms
Maintenant, étonnamment, C # est également légèrement plus rapide que Java sur le processeur ARM. Grande amélioration!
Modifier 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 en C #, en particulier que je devais l'améliorer (et donc le rendre encore plus lent). 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 natif par rapport à Java sur mon Galaxy Note 2, avec le mode d'économie d'énergie désactivé:
Java: Grand total time (5 runs): 3292 ms, avec lecture du fichier total: 3454 ms
Pouce natif: Durée totale totale (5 exécutions): 537 ms, avec lecture totale du fichier: 657 ms
Bras natif: Grand total time (5 runs): 458 ms, avec lecture du fichier total: 587 ms
On dirait que pour mon test particulier, le code natif est 6 à 7 fois plus rapide que Java. Attention: ne pouvait pas utiliser la classe std :: regex sur Android, j'ai donc dû écrire mes propres routines spécialisées à la recherche de sauts de paragraphes ou de balises html. Mes premiers tests du même code sur un PC utilisant regex, étaient environ 4 à 5 fois plus rapides que Java.
Phew! Réveillant la mémoire brute avec des pointeurs char * ou wchar *, je me suis immédiatement senti 20 ans plus jeune! :)
Modifier le 15 juillet 2013
(Veuillez 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 # sur 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 3 fois (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, j'ai donc 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 cependant pas être un gros problème. Dot42 se compile en code Dalvik (DEX), donc il coopère avec Java sur Android nativement, n'a pas besoin d'une interopérabilité coûteuse de C # vers Java comme Xamarin.
À titre de comparaison, je lance également le test sur les appareils ARM - ici, le code Dot42 est "seulement" 2x plus lent que Xamarin C #. Voici mes résultats:
HTC Nexus One Android 2.3.7 (ARM)
Java: Grand total time (5 runs): 12187 ms, avec lecture du fichier total: 13200 ms
Xamarin C #: Temps total total (5 exécutions): 13935 ms, avec un total de lecture de fichiers: 14465 ms
Dot42 C #: Durée totale totale (5 exécutions): 26000 ms, avec lecture totale du fichier: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: Grand total time (5 runs): 6895 ms, avec lecture du fichier total: 7275 ms
Xamarin C #: Temps total total (5 exécutions): 6466 ms, avec un total de lecture de fichiers: 6720 ms
Dot42 C #: Temps total total (5 passages): 11185 ms, avec total de lecture de fichiers: 11843 ms
Émulateur Intel, Android 4.2 (x86)
Java: Grand total time (5 runs): 2389 ms, avec lecture du fichier total: 2770 ms
Xamarin C #: Temps total total (5 exécutions): 1748 ms, avec total de lecture de fichiers: 1933 ms
Dot42 C #: Temps total total (5 exécutions): 5150 ms, avec un total de lecture de fichiers: 5459 ms
Pour moi, il était également intéressant de noter que Xamarin C # est légèrement plus rapide que Java sur un appareil ARM plus récent et légèrement plus lent sur l'ancien Nexus One. Si quelqu'un souhaite également exécuter 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 d'un véritable appareil Android avec processeur Intel.
Mise à jour 26/07/2013
Juste une mise à jour rapide, recompilée par des applications de référence avec la dernière version de Xamarin.Android 4.8, et également avec la mise à jour dot42 1.0.1.72 publiée aujourd'hui - aucun changement significatif par rapport aux résultats rapportés auparavant.
Mise à jour 30/07/2013 - de meilleurs résultats pour dot42
Testé de nouveau Dot42 avec le port de Robert (des fabricants de dot42) de mon code Java en C #. Dans mon port C # fait initialement pour Xamarin, j'ai remplacé certaines classes Java natives, comme ListArray, par une classe List native en C #, etc. ces endroits, ce qui profite à Dot42, je suppose parce qu'il fonctionne dans Dalvik VM, comme Java, et non en Mono, comme Xamarin. Maintenant, les résultats de Dot42 sont bien meilleurs. Voici un journal de mes tests:
30/07/2013 - Tests Dot42 avec plus de classes Java dans Dot42 C #
Émulateur Intel, Android 4.2
Dot42, Code de Greg utilisant StringBuilder.Replace () (comme dans Xamarin):
Temps total général (5 exécutions): 3646 ms, avec un total de lecture de fichiers: 3830 msDot42, le code de Greg utilisant String.Replace () (comme dans le code Java et Robert):
Temps total général (5 exécutions): 3027 ms, avec lecture totale du fichier: 3206 msDot42, Robert's Code:
Grand total time (5 runs): 1781 ms, avec lecture totale du fichier: 1999 msXamarin:
Grand total time (5 runs): 1373 ms, avec un total de lecture de fichiers: 1505 msJava:
Grand total time (5 runs): 1841 ms, avec lecture du fichier total: 2044 msARM, Samsung Galaxy Note 2, économie d'énergie, Android 4.1.1
Dot42, Greg's Code utilisant StringBuilder.Replace () (comme dans Xamarin):
Temps total total (5 exécutions): 10875 ms, avec un total de lecture de fichiers: 11280 msDot42, Code de Greg utilisant String.Replace () (comme dans le code Java et Robert):
Temps total général (5 exécutions): 9710 ms, avec total de lecture de fichiers: 10097 msDot42, Robert's Code:
Grand total time (5 runs): 6279 ms, avec total de lecture de fichiers: 6622 msXamarin:
Grand total time (5 runs): 6201 ms, avec un total de lecture de fichiers: 6476 msJava:
Grand total time (5 runs): 7141 ms, avec lecture du fichier total: 7479 ms
Je pense toujours que Dot42 a un long chemin à parcourir. Avoir des classes de type Java (par exemple ArrayList) et de bonnes performances avec elles rendrait le portage de code de Java vers C # légèrement plus facile. Cependant, c'est quelque chose que je ne ferais probablement pas beaucoup. Je préférerais utiliser le code C # existant (bibliothèques, etc.), qui utilisera des classes C # natives (par exemple, List), et cela fonctionnerait lentement avec le code dot42 actuel, et très bien avec Xamarin.
Greg