Buscar
Social
Ofertas laborales ES
« JDK 7u51, Derby Network y Security Manager | Main | Pregunta sobre privacidad de datos - Google »
viernes
ene242014

Desarrollo y optimización de aplicaciones para Android* en la plataforma Intel® Atom™

Nota: Este tutorial ha sido donado a la comunidad de javaHispano por Intel. Intel espera que en el futuro sus procesadores incrementen considerablemente su presencia en los terminales móviles Android, por ello ha creído que este artículo sería interesante para nuestra comunidad. El artículo puede encontrarse en la web de Intel aquí.

Resumen

Este documento introduce métodos detallados para el desarrollo y migración de una aplicación Android en la plataforma Intel Atom, y describe los métodos más conocidos para desarrollar aplicaciones mediante el Kit para desarrollo nativo para Android (NDK) y para optimizar el rendimiento. Los desarrolladores para Android pueden utilizar este documento como una referencia para crear aplicaciones de alta calidad para la arquitectura Intel.

1. Clasificación de aplicaciones para Android

Las aplicaciones para Android pueden clasificarse en dos tipos, tal como se muestra en la Ilustración 1.

  • Las aplicaciones Dalvik que incluyen código Java* y utilizan solo la API del SDK oficial para Android y los archivos de los recursos necesarios, tales como xml y png, compilados en un archivo APK.
  • Las aplicaciones NDK para Android que incluyen el código Java y los archivos de recursos, así como el código de recursos C/C++ y, algunas veces, el código ensamblador. Todo el código nativo se compila en una biblioteca vinculada dinámica (un archivo .so) y, posteriormente, Java la llama en el programa principal mediante un mecanismo de JNI.


Ilustración 1: Dos tipos de aplicaciones para Android

2. Kit de desarrollo nativo para Android

2.1 Introducción

El Kit de desarrollo nativo para Android (NDK) es una herramienta que complementa al SDK de Android. El NDK es una herramienta poderosa para el desarrollo de aplicaciones para Android debido a que:

  • Crea porciones cruciales para el rendimiento de sus aplicaciones en código nativo. Cuando se utiliza el código Java, el código fuente basado en Java necesita ser interpretado en un idioma informático mediante un equipo virtual. En cambio, el código nativo se compila y optimiza en código binario directamente antes de la ejecución. Con el uso apropiado del código nativo, puede crear código de alto rendimiento en su aplicación, tal como codificado y decodificado de video de hardware, proceso de gráficos y operaciones aritméticas.
  • Reutiliza el código nativo legado. Los códigos C/C++ se compilan en una biblioteca dinámica que el código Java puede llamar con un mecanismo de JNI.

2.2 Descripción general de las herramientas

Durante el período de desarrollo, puede utilizar Intel® Hardware Execution Manager (HAXM) para mejorar el rendimiento del simulador para Android. HAXM es un motor de virtualización con la ayuda de hardware (hipervisor) que utiliza la Tecnología Intel® de virtualización para acelerar la emulación de aplicaciones para Android en un equipo huésped. En combinación con imágenes del emulador para Android x86 que Intel proporciona y el Administrador de Android SDK oficial, HAXM resulta en una experiencia de emulación para Android más rápida en sistemas habilitados para la Tecnología Intel® de virtualización. Para obtener más información sobre HAXM, visite: http://software.intel.com/es-es/articles/intel-hardware-accelerated-execution-manager.

2.3 Instalación de HAXM

Utilice el Administrador de Android SDK para instalar HAXM (recomendable) o, para hacerlo manualmente, descargue el instalador del sitio web de Intel. Si desea actualizarlo automáticamente, instálelo con el administrador del Android SDK, tal como se muestra en la Ilustración 2. [1]


Ilustración 2: Instalar Intel HAXM con el Administrador de Android SDK

También puede descargar un paquete de instalación adecuado desde http://software.intel.com/es-es/android a su plataforma huésped y seguir las instrucciones paso a paso para instalarlo.

2.3.1 Configuración de HAXM

Cuando se ejecuta HAXM, se requiere la imagen del sistema Android x86 que Intel proporciona. Puede descargar la imagen del sistema usando el Administrador de Android SDK o descargarla manualmente del sitio web de la Zona para desarrolladores Intel®.

Después de que las imágenes se instalan satisfactoriamente, las imágenes del emulador de Intel® x86 Android se ejecutan automáticamente utilizando el binario del “emulator-x86” proporcionado con el Android SDK. La Tecnología Intel® de virtualización acelera el emulador Android, lo cual acelera su proceso de desarrollo.

3. Desarrollo y migración de aplicaciones NDK para la Arquitectura de Intel Atom

3.1 Desarrollo de aplicaciones NDK para los dispositivos basados en el procesador Intel Atom

Después de instalar el NDK satisfactoriamente, dedique unos minutos a leer los documentos del directorio <ndk>/docs/, especialmente los denominados OVERVIEW.html y CPU-X86.html, para familiarizarse con el mecanismo del NDK y cómo utilizarlo.

El desarrollo de la aplicación NDK puede dividirse en cinco pasos que se muestran en la Ilustración 3:


Ilustración 3: Proceso del desarrollo de la aplicación NDK

Para ilustrar estos cinco pasos, se utiliza la demostración de hello-jni. Puede encontrar esta demostración en la carpeta NDK Root\samples\hello-jni [5]. La demostración de Hello-jni es una aplicación simple incluida en el NDK que obtiene una cadena de un método nativo en una biblioteca compartida y la utiliza en la interfaz de usuario de la aplicación.

3.1.1. Creación del código nativo

Cree un nuevo proyecto para Android y coloque su código fuente nativo bajo <proyecto>/jni/. El contenido del proyecto se muestra en la Ilustración 4. Esta demostración incluye una simple función en código nativo denominada Java_com_example_hellojni_HelloJni_stringFromJNI(). Tal como se muestra en el código fuente, devuelve una cadena simple de JNI.


Ilustración 4: Creación del código nativo

3.1.2 Creación de MakeFile ‘Android.mk’

Las aplicaciones del NDK se crean para la plataforma ARM de manera predeterminada. Para crear aplicaciones NDK para la plataforma Intel Atom, es necesario agregar APP_ABI := x86 al MakeFile.


Ilustración 5: Creación de MakeFile

3.1.3 Compilación de código nativo

Cree un código nativo al ejecutar la secuencia de comandos 'ndk-build' desde el directorio del proyecto. Se encuentra en el directorio principal de NDK. El resultado aparece en la Ilustración 6.


Ilustración 6: Código nativo compilado

Las herramientas de creación copian automáticamente las bibliotecas compartidas esenciales a la ubicación pertinente en el directorio del proyecto de la aplicación.

3.1.4 Llamada del código nativo de Java

Cuando despliega la biblioteca compartida satisfactoriamente, puede llamar la función desde Java. El código se muestra en la Ilustración 7. Se crea una llamada de la función nativa pública stringFromJNI() en el código Java y esta función carga la biblioteca compartida con System.loadlibrary().


Ilustración 7: Llamada de código nativo desde Java

3.1.5 Depuración con GDB

Si desea depurar la aplicación NDK con GDB, es necesario satisfacer las siguientes condiciones:

  • La aplicación NDK se crea con 'ndk-build'
  • La aplicación NDK se establece en ‘debuggable’ en Android.manifest
  • La aplicación NDK se ejecuta en Android 2.2 (o superior)
  • Un solo destino está en ejecución
  • Hay que agregar el directorio adb a PATH

Utilice el comando ndk-gdb para depurar la aplicación. Puede definir ya sea un punto de interrupción o una depuración paso a paso para realizar un seguimiento del historial de cambios de un valor variable, tal como muestra la Ilustración 8.


Ilustración 8: Depuración de la aplicación NDK con GDB

3.2 Migración de aplicaciones NDK existentes a dispositivos basados en el procesador Intel Atom

En esta sección, se asume que tiene una aplicación Android para la plataforma ARM y necesita migrarla antes de desplegarla en la plataforma Intel Atom.

La migración de las aplicaciones Android a la plataforma Intel Atom es similar al proceso de desarrollo. Los pasos se muestran en la Ilustración 9.


Ilustración 9: Migración de aplicaciones Android a la plataforma Intel Atom

3.2.1 Migración de aplicaciones Dalvik

Las aplicaciones Dalvik pueden ejecutarse directamente en los dispositivos basados en el procesador Intel Atom. La interfaz de usuario necesita ajustarse para el dispositivo de destino. Para un dispositivo de alta resolución, tales como tabletas con una resolución de 1280*800 o superior, la asignación de memoria predeterminada posiblemente no cumpla con los requisitos de la aplicación, lo cual impide que pueda lanzarse. Se recomienda el incremento de la asignación de memoria predeterminada para los dispositivos de alta resolución.

3.2.2 Migración de aplicaciones NDK para Android

La migración de aplicaciones NDK es un poco más complicada que la migración de aplicaciones Dalvik. Todas las aplicaciones NDK se pueden dividir en tres tipos según las siguientes propiedades del código nativo:

  • Consiste en código C/C++ solo que no está relacionado con el hardware
  • Utiliza una biblioteca vinculada dinámica de terceros
  • Incluye código ensamblador que está altamente relacionado con plataformas que no son la arquitectura Intel

Código nativo que consiste en código C/C++ solo que no está relacionado con el hardware

  1. Recompile el código nativo para ejecutar la aplicación satisfactoriamente en la plataforma Intel Atom.
  2. Abra el proyecto de NDK, busque el archivo Android.mk, agregue APP_ABI := armeabi armeabi-v7a x86 en Android.mk y reconstruya el código nativo con ndk-build.
  3. Si no encuentra el archivo Android.mk, utilice el comando ndk-build APP_ABI="armeabi armeabi-v7a x86" para crear el proyecto.
  4. Vuelva a encapsular la aplicación con las plataformas x86 compatibles.

Si el código nativo utiliza una biblioteca vinculada dinámica de terceros, la biblioteca compartida debe volver a compilarse en la versión x86 para la plataforma Intel Atom.

Si el código nativo incluye código ensamblador que esté altamente relacionado con las plataformas que no son de la arquitectura Intel,entonces el código debe volver a escribirse con ensamblador de la arquitectura Intel o C/C++.

4. Métodos más conocidos para desarrollar el código nativo

4.1 Alineación de memoria forzada

Debido a diferencias entre las arquitecturas, plataformas y compiladores, puede que los tamaños de los datos de la estructura de los mismos datos en distintas plataformas sean diferentes. Sin la alineación de memoria forzada, pueden existir errores de carga para tamaños de datos incoherentes. [2]

El siguiente ejemplo describe los tamaños de datos de la misma estructura de datos en distintas plataformas:

struct TestStruct {
int mVar1;
long long mVar2;
int mVar3;
 };

Esta es una estructura simple con tres variables denominadas mVar1, mVar2 y mVar3.

mVar1 es un int y utilizará 4 bytes
mVar2 es long long int que utilizará 8 bytes
mVar3 también es int, utilizará 4 bytes.

¿Cuántos espacios se necesitan en las plataformas ARM e Intel Atom?

El tamaño de los datos compilados para las plataformas ARM e Intel Atom con un interruptor de compilador predeterminado se muestra en la Ilustración 10. ARM adopta automáticamente doble malign y ocupa 24 bytes, mientras que x86 ocupa 16 bytes.


Ilustración 10: Memoria asignada por marcadores de compilación predeterminados

La variable mVar2 de 8 bytes (64 bits) resulta en un diseño distinto para TestStruct debido a que ARM requiere una alineación de 8 bytes para variables de 64 bits igual que mVar2. En la mayoría de los casos, esto no causa problemas debido a que crear para x86 vs. ARM requiere una reconstrucción completa.

No obstante, una incoherencia de tamaños podría presentarse si una aplicación serializa clases o estructuras. Por ejemplo, usted crea un archivo en una aplicación de ARM y escribe TestStruct en un archivo. Si posteriormente carga los datos desde ese archivo a una plataforma x86, el tamaño de la clase en la aplicación es diferente en el archivo. Problemas similares de alineación de memorias pueden ocurrir en el tráfico de redes que anticipa un diseño de memoria específico.

La opción “-malign-double” del compilador GCC genera la misma alineación de memoria en x86 y en ARM.


Ilustración 11: Memoria asignada cuando se agregan marcadores -malign-double

4.2 Instrucciones de migración de NEON* a SSE [3]

4.2.1 NEON

La tecnología NEON* de ARM se utiliza principalmente en multimedios tales como aplicaciones de smartphones y HDTV. Según la documentación de ARM, su tecnología basada en el motor SIMD de 128 bits, la cual es una extensión de ARM Cortex*–A Series, ofrece al menos 3 veces más rendimiento que la arquitectura de ARMv5 y al menos 2 veces más que la versión subsiguiente: ARMv6. Para obtener más información sobre la tecnología NEON visite: http://www.arm.com/products/processors/technologies/neon.php.

4.2.2 SSE: El equivalente de Intel

SSE es la Streaming SIMD Extension para la arquitectura Intel (IA). En la actualidad, el procesador Intel Atom es compatible con SSSE3 (Supplemental Streaming SIMD Extensions 3) y las versiones anteriores, pero todavía no es compatible con SSE4.x. SSE es un motor de 128 bits que acepta el encapsulamiento de los datos de puntos flotantes. El modelo de ejecución comenzó con la tecnología MMX y SSx es esencialmente la generación más reciente que reemplaza la necesidad de MMX. Para obtener más información, consulte la sección "Volume 1: Basic Architecture" (Volumen 1: Arquitectura básica) de los Manuales para Desarrolladores de software para las Arquitecturas Intel de 64 y 32 bits. La descripción general de SSE, que se encuentra en la sección 5.5, proporciona las instrucciones para SSE, SSE2, SSE3 y SSSE3. Estas operaciones de datos mueven valores de puntos flotantes basados en precisión y de alto contenido entre los registros de XMM o entre los registros de MMX y la memoria. Los registros de XMM fueron diseñados para usarse como un reemplazo de los registros de MMX.

4.2.3 De NEON a SSE a nivel de ensamblador

Cuando utilice el Manual para desarrolladores de software de la arquitectura Intel como una referencia cruzada para todos los mnemotécnicos SSE(x) individuales, examine también las distintas instrucciones al nivel de ensamblador de SSE ubicadas en:http://neilkemp.us/src/sse_tutorial/sse_tutorial.html. Utilice la tabla de contenido para acceder los ejemplos del código o examine los antecedentes.

De manera similar, el siguiente manual de ARM proporciona información sobre NEON y contiene pequeños fragmentos de código ensamblador en la sección 1.4,”Developing for NEON” (Desarrollo para NEON):http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf.

Diferencias clave al comparar el código ensamblador NEON y SSE:

  • Capacidades Endian. Intel es compatible solo con el ensamblaje de marcadores little-endian, mientras que ARM es compatible con el orden de marcadores endian grandes "big" o pequeños "little" (ARM acepta ambos, es bi-endian). En los ejemplos de código proporcionados, el código ARM es little-endian similar a Intel. Nota: Es posible que existan algunas implicaciones con el compilador de ARM. Por ejemplo, la compilación para ARM utilizando GCC incluye marcadores –mlittle-endian y –mbig-endian. Para obtener más información consulte http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.
  • Granularidad. En el caso de los ejemplos de código de ensamblaje simple a los que hacemos referencia, compare las instrucciones de ADDPS para SSE (Intel) con VADD.ix para NEON tales como x = 8 ó 16. Observe que este último valor agrega cierta granularidad a los datos que se administrarán como parte del mnemotécnico al que se hace referencia.

Nota: Estas diferencias no son todas las que existen. Puede ver otras diferencias entre NEON y SSE.

4.2.4 De NEON a SSE a nivel de C/C++

Pueden presentarse muchas dificultades de la API durante la migración del código C/C++ y NEON a SSE. Tenga en mente que asumimos que no se utilizará ensamblador inline, que en su lugar se utilizará el código C/C++ verdadero. Las instrucciones NEON también proveen algunas bibliotecas C nativas. Aunque estas instrucciones son código C, no pueden ejecutarse en la plataforma Intel Atom y deben volver a escribirse.

5. Optimización del rendimiento de la aplicación

5.1 Ajuste de rendimiento

Durante el proceso de codificación, utilice los siguientes métodos para optimizar el rendimiento de su aplicación en la plataforma Intel Atom.

5.1.1 Uso de Inline (en línea) en lugar Frequently Used Short (corto utilizado frecuentemente)

Las funciones Inline son mejores para funciones pequeñas tales como el acceso a miembros de datos privados. Las funciones cortas son sensibles al impacto de las llamadas de funciones. Las funciones más largas demoran menos tiempo, de manera proporcionada, en la secuencia de llamadas/llamadas de regreso y se benefician menos de las funciones en línea. [4]

La función Inline (en línea) ahorra la sobrecarga en:

  • Las llamadas de funciones (inclusive el paso de parámetros y la colocación de la dirección del objeto en la pila)
  • Preservación del marco de la pila de la rutina que llama
  • Nueva configuración de pila y marco
  • Comunicación de valor y retorno
  • Restauración de pila y marco anteriores
  • Retorno

5.1.2 Uso de flotante en lugar de doble

FPU es una unidad de punto flotante que es una parte de un sistema especialmente diseñado para llevar a cabo operaciones en los números de puntos flotantes, tales como: suma, resta, multiplicación, división y raíz cuadrada. Algunos sistemas (especialmente las arquitecturas antiguas y basadas en microcódigo) también pueden realizar varias funciones trascendentales tales como cálculos exponenciales o trigonométricos. Los procesadores actuales realizan estos cálculos con rutinas de bibliotecas de software. En la mayoría de las arquitecturas de computadoras modernas para fines generales, una o más FPU están integradas con la CPU [6].

La plataforma Intel Atom tiene la FPU habilitada. En la mayoría de los casos, el usar puntos flotantes en lugar de dobles acelera el proceso de computación de datos y ahorra el ancho de banda de la memoria en los dispositivos basados en el procesador Intel Atom.

5.1.3 Codificación de multisubprocesos

El codificado de multisubprocesos le permite utilizar la función hyper-threading del procesador Intel Atom para aumentar los resultados y mejorar el rendimiento general. Para obtener más información sobre multisubprocesamiento, consulte: http://www.intel.com/content/www/es/es/architecture-and-technology/hyper-threading/hyper-threading-technology.html.

5.2 Creación de aplicaciones de alto rendimiento con marcadores de compilador

Como usted sabe, el código nativo es creado por GCC en aplicaciones para Android. Pero, ¿sabe cuál es el dispositivo de destino predeterminado de GCC? Es el procesador Pentium® Pro. El código binario de destino se ejecuta mejor en la plataforma Pentium Pro si no agrega ningún marcador durante la compilación del código nativo. La mayoría de las aplicaciones para Android se ejecutan en la plataforma Intel Atom en lugar de Pentium Pro. Se recomienda enfáticamente agregar marcadores específicos según su plataforma de destino. Puede agregar los siguientes marcadores recomendados durante la compilación en la plataforma Intel Atom:

-march=atom
-msse4
-mavx
-maes

Para obtener más información sobre los parámetros del compilador, consulte: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html.

6. Conclusión

Este documento describe la manera de desarrollar y optimizar las aplicaciones para Android en las plataformas Intel Atom, así como la manera de desarrollar y migrar aplicaciones del NDK.

Un resumen de los puntos clave es:

  • La mayoría de las aplicaciones para Android pueden ejecutarse directamente en la plataforma Intel Atom. Las aplicaciones de NDK necesitan recompilar el código nativo. Si el código ensamblador se incluye en la aplicación, esta porción del código debe volver a escribirse.
  • Aproveche al máximo las funciones de la arquitectura Intel para mejorar el rendimiento de su aplicación para Android.
  • Agregue interruptores de compilación específicos a la plataforma para que el código de creación GCC sea más efectivo.

Referencia

  1. http://software.intel.com/es-es/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows/
  2. http://software.intel.com/es-es/blogs/2011/08/18/understanding-x86-vs-arm-memory-alignment-on-android/
  3. http://software.intel.com/es-es/articles/ndk-android-application-porting-methodologies/
  4. http://msdn.microsoft.com/es-es/library/1w2887zk.aspx
  5. http://developer.android.com/sdk/ndk/index.html
  6. http://es.wikipedia.org/wiki/Unidad_de_coma_flotante

Sobre el autor

Dawei es un ingeniero de aplicaciones dedicado a la habilitación de aplicaciones para móviles, incluyendo el desarrollo y optimización de aplicaciones Android para dispositivos x86, y el desarrollo de aplicaciones con HTML5 para la web. Además, Dawei también tiene amplia experiencia en el diseño de interfaces de usuario y experiencias de usuario de aplicaciones.

 

El blog de Xavier Hallade, Software Engineer - Intel : http://ph0b.com/
Para cualquier pregunta, póngase en contacto con Slim Soussi, EMEA Program Manager - Intel
(en ingles por favor) slim.soussi@intel.com

 

 

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (4)

Como programador preferiría que los fabricantes de chips adaptaran sus procesadores que ejecutaran mi código más rápidamente y no que yo tenga que adaptar mi código para que sus procesadores puedan funcionar de forma optima. ¿Por qué no un procesador que ejecute nativamente el código byte de Java?

enero 24, 2014 | Registered Commenterjavierpaniza

Según tengo entendido, ART es precisamente lo que va a hacer, no? al instalar un APK, lo compila a binario, ya no se usaría el bytecode para ejecutar la aplicacion.


Saludos.

enero 24, 2014 | Unregistered CommenterLokillo

Ese traductor de google bueno.. "mientras que ARM es compatible con el orden de marcadores endian grandes "big" o pequeños "little""

enero 25, 2014 | Unregistered Commenterasd

@Javierpaniza, eso ya existe desde hace años. Los procesadores ARM tienen soporte nativo para Java (mirar http://en.wikipedia.org/wiki/Jazelle#Successor:_ThumbEE y http://en.wikipedia.org/wiki/ARM_architecture#Thumb_Execution_Environment_.28ThumbEE.29). Esta característica viene principalmente de cuando JavaME era el no va más en los móviles, pero actualmente ningún gran fabricante está interesado en soportar Java nativo en ARM.

Por otro lado no es suficiente con que el HW sea capaz de interpretar nativamente Java para que sea más eficiente. Por construcción, Java no será nunca tan eficiente como lenguajes de más bajo nivel. Características como el linkado dinámico, las funciones virtuales, control de buffer overflow o funcionar con una pila en lugar de en base a registros, es algo que siempre se notará, por lo que los que quieran exprimir al máximo su sistema seguirán enfocándose más en otros lenguajes.

Por otro lado, con la capacidad de los procesadores móviles actuales y gracias a JNI, la mayoría de las aplicaciones tienen un rendimiento excelente estando escritas en Java.

enero 28, 2014 | Registered Commentergolthiryus

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>