¿Cómo comparar el rendimiento de las aplicaciones de Android escritas en Java y Xamarin C#? De todos modos para verificar datos cuantitativos (código y resultados) [cerrado]
Me encontré con que Xamarin afirma que su implementación Mono en Android y sus aplicaciones compiladas en C# son más rápidas que el código Java. ¿Alguien realizó pruebas comparativas reales en código Java y C# muy similar en diferentes plataformas Android para verificar tales afirmaciones? ¿Podría publicar el código y los resultados?
Añadido el 18 de junio de 2013
Como no hubo respuesta y no pude encontrar puntos de referencia realizados por otros, decidí hacer mis propias pruebas. Desafortunadamente, mi pregunta permanece "bloqueada", por lo que no puedo publicarla como respuesta, solo editar la pregunta. Vote para reabrir esta pregunta. Para C#, utilicé Xamarin.Android Ver. 4.7.09001 (beta). El código fuente, todos los datos que utilicé para las pruebas y los paquetes APK compilados están en GitHub:
Java: https://github.com/gregko/TtsSetup_Java
C#: https://github.com/gregko/TtsSetup_C_sharp
Si alguien quisiera repetir mis pruebas en otros dispositivos o emuladores, también me interesaría conocer los resultados.
Resultados de mis pruebas
Porté mi clase de extractor de oraciones a C# (desde mi aplicación @Voice Aloud Reader) y realicé algunas pruebas en 10 archivos HTML en inglés, ruso, francés, polaco y checo. Cada ejecución se realizó 5 veces en los 10 archivos y el tiempo total para 3 dispositivos diferentes y un emulador se publica a continuación. Probé solo compilaciones de "lanzamiento", sin la depuración habilitada.
HTC Nexus One Android 2.3.7 (API 10) - ROM CyanogenMod
Java: tiempo total general (5 ejecuciones): 12361 ms, con lectura total de archivos: 13304 ms
C#: tiempo total general (5 ejecuciones): 17504 ms, con lectura total de archivos: 17956 ms
Samsung Galaxy S2 SGH-I777 (Android 4.0.4, API 15) - ROM CyanogenMod
Java: tiempo total general (5 ejecuciones): 8947 ms, con lectura total de archivos: 9186 ms
C#: tiempo total general (5 ejecuciones): 9884 ms, con lectura total de archivos: 10247 ms
Samsung GT-N7100 (Android 4.1.1 JellyBean, API 16) - ROM de Samsung
Java: tiempo total general (5 ejecuciones): 9742 ms, con lectura total de archivos: 10111 ms
C#: tiempo total general (5 ejecuciones): 10459 ms, con lectura total de archivos: 10696 ms
Emulador: Intel (Android 4.2, API 17)
Java: tiempo total general (5 ejecuciones): 2699 ms, con lectura total de archivos: 3127 ms
C#: tiempo total general (5 ejecuciones): 2049 ms, con lectura total de archivos: 2182 ms
Emulador: Intel (Android 2.3.7, API 10)
Java: tiempo total general (5 ejecuciones): 2992 ms, con lectura total de archivos: 3591 ms
C#: tiempo total general (5 ejecuciones): 2049 ms, con lectura total de archivos: 2257 ms
Emulador: Arm (Android 4.0.4, API 15)
Java: tiempo total general (5 ejecuciones): 41751 ms, con lectura total de archivos: 43866 ms
C#: Tiempo total general (5 ejecuciones): 44136 ms, con lectura total de archivos: 45109 ms
Breve discusión
Mi código de prueba contiene principalmente análisis de texto, reemplazo y búsquedas de expresiones regulares; tal vez para otro código (por ejemplo, operaciones más numéricas) los resultados serían diferentes. En todos los dispositivos con procesadores ARM, Java funcionó mejor que el código Xamarin C#. La mayor diferencia se produjo en Android 2.3, donde el código C# se ejecuta a aprox. 70% de la velocidad de Java.
En el emulador Intel (con tecnología Intel HAX, el emulador se ejecuta en modo virt rápido), el código Xamarin C# ejecuta mi código de muestra mucho más rápido que Java, aproximadamente 1,35 veces más rápido. ¿Quizás el código y las bibliotecas de la máquina virtual Mono estén mucho mejor optimizados en Intel que en ARM?
Editar 8 de julio de 2013
Acabo de instalar el emulador de Android Genymotion, que se ejecuta en Oracle VirtualBox, y nuevamente este usa un procesador Intel nativo, no emula el procesador ARM. Al igual que con el emulador Intel HAX, nuevamente C# se ejecuta aquí mucho más rápido. Aquí están mis resultados:
Emulador Genymotion - Intel (Android 4.1.1, API 16)
Java: tiempo total general (5 ejecuciones): 2069 ms, con lectura total de archivos: 2248 ms
C#: tiempo total general (5 ejecuciones): 1543 ms, con lectura total de archivos: 1642 ms
Luego noté que había una actualización de Xamarin.Android beta, versión 4.7.11, con notas de la versión que también mencionaban algunos cambios en el tiempo de ejecución de Mono. Decidí probar rápidamente algunos dispositivos ARM y me llevé una gran sorpresa: los números de C# mejoraron:
BN Nook XD+, ARM (Android 4.0)
Java: Tiempo total general (5 ejecuciones): 8103 ms, con lectura total de archivos: 8569 ms
C#: Tiempo total general (5 ejecuciones): 7951 ms, con lectura total de archivos: 8161 ms
¡Guau! ¿C# es ahora mejor que Java? Decidí repetir la prueba en mi Galaxy Note 2:
Samsung Galaxy Note 2 - ARM (Android 4.1.1)
Java: tiempo total general (5 ejecuciones): 9675 ms, con lectura total de archivos: 10028 ms
C#: tiempo total general (5 ejecuciones): 9911 ms, con lectura total de archivos: 10104 ms
Aquí C# parece ser sólo un poco más lento, pero estos números me hicieron hacer una pausa: ¿Por qué el tiempo es más largo que en Nook HD+, a pesar de que el Note 2 tiene un procesador más rápido? La respuesta: modo de ahorro de energía. En Nook estaba deshabilitado, en Note 2, habilitado. Decidí probar con el modo de ahorro de energía desactivado (al igual que cuando está activado, también limita la velocidad del procesador):
Samsung Galaxy Note 2 - ARM (Android 4.1.1), ahorro de energía desactivado
Java: tiempo total general (5 ejecuciones): 7153 ms, con lectura total de archivos: 7459 ms
C#: tiempo total general (5 ejecuciones): 6906 ms, con lectura total de archivos: 7070 ms
Ahora, sorprendentemente, C# también es un poco más rápido que Java en el procesador ARM. ¡Gran mejora!
Editar 12 de julio de 2013
Todos sabemos que nada supera al código nativo en cuanto a velocidad, y no estaba satisfecho con el rendimiento de mi divisor de oraciones en Java o C#, particularmente porque necesito mejorarlo (y así hacerlo aún más lento). Decidió reescribirlo en C++. Aquí hay una pequeña comparación (es decir, un conjunto de archivos más pequeño que las pruebas anteriores, por otras razones) de la velocidad de Java nativo versus Java en mi Galaxy Note 2, con el modo de ahorro de energía desactivado:
Java: tiempo total general (5 ejecuciones): 3292 ms, con lectura total de archivos: 3454 ms
Pulgar nativo: tiempo total general (5 ejecuciones): 537 ms, con lectura de archivos total: 657 ms
Brazo nativo: tiempo total general (5 ejecuciones): 458 ms, con lectura de archivos total: 587 ms
Parece que para mi prueba particular, el código nativo es de 6 a 7 veces más rápido que Java. Advertencia: no pude usar la clase std::regex en Android, por lo que tuve que escribir mis propias rutinas especializadas en busca de saltos de párrafo o etiquetas html. Mis pruebas iniciales del mismo código en una PC usando expresiones regulares fueron entre 4 y 5 veces más rápidas que Java.
¡Uf! Al despertar de nuevo la memoria sin procesar con punteros char* o wchar*, ¡instantáneamente me sentí 20 años más joven! :)
Editar 15 de julio de 2013
(Consulte a continuación, con ediciones del 30/7/2013, para obtener resultados mucho mejores con Dot42)
Con cierta dificultad, logré portar mis pruebas de C# a Dot42 (versión 1.0.1.71 beta), otra plataforma de C# para Android. Los resultados preliminares muestran que el código Dot42 es aproximadamente 3 veces (3 veces) más lento que Xamarin C# (v. 4.7.11), en un emulador Intel de Android. Un problema es que la clase System.Text.RegularExpressions en Dot42 no tiene la función Split() que usé en las pruebas de Xamarin, así que usé la clase Java.Util.Regex y Java.Util.Regex.Pattern.Split(). , entonces en este lugar particular del código, existe esta pequeña diferencia. Aunque no debería ser un gran problema. Dot42 compila en código Dalvik (DEX), por lo que coopera con Java en Android de forma nativa, no necesita una costosa interoperabilidad de C# a Java como Xamarin.
Solo a modo de comparación, también ejecuto la prueba en dispositivos ARM; aquí el código Dot42 es "sólo" 2 veces más lento que Xamarin C#. Aquí están mis resultados:
HTC Nexus One Android 2.3.7 (ARM)
Java: tiempo total general (5 ejecuciones): 12187 ms, con lectura total de archivos: 13200 ms
Xamarin C#: Tiempo total general (5 ejecuciones): 13935 ms, con lectura de archivos total: 14465 ms
Dot42 C#: tiempo total general (5 ejecuciones): 26000 ms, con lectura de archivos total: 27168 ms
Samsung Galaxy Note 2, Android 4.1.1 (ARM)
Java: tiempo total general (5 ejecuciones): 6895 ms, con lectura total de archivos: 7275 ms
Xamarin C#: Tiempo total general (5 ejecuciones): 6466 ms, con lectura de archivos total: 6720 ms
Dot42 C#: Tiempo total general (5 ejecuciones): 11185 ms, con lectura de archivos total: 11843 ms
Emulador Intel, Android 4.2 (x86)
Java: tiempo total general (5 ejecuciones): 2389 ms, con lectura total de archivos: 2770 ms
Xamarin C#: tiempo total general (5 ejecuciones): 1748 ms, con lectura total de archivos: 1933 ms
Dot42 C#: tiempo total general (5 ejecuciones): 5150 ms, con lectura de archivos total: 5459 ms
Para mí, también fue interesante notar que Xamarin C# es ligeramente más rápido que Java en un dispositivo ARM más nuevo y un poco más lento en el antiguo Nexus One. Si alguien también desea ejecutar estas pruebas, hágamelo saber y actualizaré las fuentes en GitHub. Sería particularmente interesante ver los resultados de un dispositivo Android real con procesador Intel.
Actualización 26/07/2013
Solo una actualización rápida, recompilada por aplicaciones de referencia con la última versión de Xamarin.Android 4.8 y también con la actualización dot42 1.0.1.72 lanzada hoy; no hay cambios significativos con respecto a los resultados informados anteriormente.
Actualización 30/07/2013: mejores resultados para dot42
Volví a probar Dot42 con la adaptación de Robert (de los fabricantes de dot42) de mi código Java a C#. En mi adaptación de C# realizada inicialmente para Xamarin, reemplacé algunas clases nativas de Java, como ListArray, con la clase List nativa de C#, etc. Robert no tenía mi código fuente Dot42, por lo que lo portó nuevamente desde Java y usó clases de Java originales en tales lugares, lo que beneficia a Dot42, supongo, porque se ejecuta en Dalvik VM, como Java, y no en Mono, como Xamarin. Ahora los resultados de Dot42 son mucho mejores. Aquí hay un registro de mis pruebas:
30/07/2013 - Pruebas de Dot42 con más clases de Java en Dot42 C#
Emulador Intel, Android 4.2
Dot42, código de Greg usando StringBuilder.Replace() (como en Xamarin):
tiempo total general (5 ejecuciones): 3646 ms, con lectura total de archivos: 3830 msDot42, código de Greg usando String.Replace() (como en Java y el código de Robert):
tiempo total general (5 ejecuciones): 3027 ms, con lectura total de archivos: 3206 msDot42, Código de Robert:
tiempo total general (5 ejecuciones): 1781 ms, con lectura de archivos total: 1999 msXamarin:
tiempo total general (5 ejecuciones): 1373 ms, con lectura de archivos total: 1505 msJava:
tiempo total general (5 ejecuciones): 1841 ms, con lectura total de archivos: 2044 msARM, Samsung Galaxy Note 2, ahorro de energía desactivado, Android 4.1.1
Dot42, código de Greg usando StringBuilder.Replace() (como en Xamarin):
tiempo total general (5 ejecuciones): 10875 ms, con lectura total de archivos: 11280 msDot42, código de Greg usando String.Replace() (como en Java y el código de Robert):
tiempo total general (5 ejecuciones): 9710 ms, con lectura total de archivos: 10097 msDot42, Código de Robert:
tiempo total general (5 ejecuciones): 6279 ms, con lectura de archivos total: 6622 msXamarin:
tiempo total general (5 ejecuciones): 6201 ms, con lectura de archivos total: 6476 msJava:
tiempo total general (5 ejecuciones): 7141 ms, con lectura total de archivos: 7479 ms
Sigo pensando que a Dot42 le queda un largo camino por recorrer. Tener clases similares a Java (por ejemplo, ArrayList) y un buen rendimiento con ellas facilitaría un poco la transferencia de código de Java a C#. Sin embargo, esto es algo que probablemente no haría mucho. Preferiría usar código C# existente (bibliotecas, etc.), que usará clases nativas de C# (por ejemplo, Lista), y que funcionaría lentamente con el código dot42 actual y muy bien con Xamarin.
Greg
Me encontré con esta interesante publicación:
https://medium.com/@harrycheung/mobile-app-rendimiento-redux-e512be94f976#.kfbauchtz
Recientemente investigamos el uso de Xamarin para una aplicación. Utilizamos el código C# que ya habíamos escrito para la versión Windows RT de nuestra aplicación. Se tuvieron que reescribir algunos detalles específicos para la versión de Android.
Lo que descubrimos es que la E/S en Xamarin C# es aproximadamente 2 veces más lenta que Java. Nuestra aplicación está fuertemente vinculada a E/S. Aún no hemos descubierto la causa de esto, pero por el momento suponemos que se debe a la clasificación. Si bien intentamos permanecer dentro de Mono VM la mayor parte del tiempo, no sabemos cómo Mono realmente accede al disco.
También es revelador que nuestro código C# usa SQLite.NET ( https://github.com/praeclarum/sqlite-net ). Las recuperaciones idénticas usando el código SQLite.NET también son 2 veces más lentas que usando el contenedor Java SQLite de Android. Después de mirar el código fuente, parece vincularse directamente al C .dll, así que no sé por qué es mucho más lento. Una posibilidad es que la clasificación de cadenas nativas a Java pueda ser más rápida en Android que la nativa a C# en Xamarin.
Esta es otra publicación de blog más actualizada que me gustaría compartir con ustedes . Compara Xamarin con código nativo y Cordova tanto en IO como en Android.
En pocas palabras, Xamarin a veces funciona mejor que el código nativo. Probó el tamaño de la aplicación, los tiempos de carga, la carga de una lista desde el servicio Azure y el cálculo de números primos.
¡Disfrutar!
Edit: I updated the dead link and I noticed that there is a part 2