Comment j'ai optimisé mes applications Android (NDK) en 2 minutes sur les architectures Intel.

Je suis Jean-Claude Cottier, un vétéran de l'industrie du jeu vidéo. Cela fait 18 ans que je travaille dans ce milieu. En 2008 j'ai fondé mon propre studio : Ovogame. C'est une toute petite structure puisque je suis le seul à y travailler à plein temps. Je produits mes jeux sur un maximum de supports et particulièrement sur les plateformes Android : http://www.ovogame.com/android/googleplay. Récemment, je les ai optimisés pour les architectures Intel et cela a été un jeu d’enfant.

Pour créer mes jeux, j’utilise ma propre technologie : un moteur C++ multiplateformes (Android, iOS, BB10, Win32 et OSX). Je développe quasi exclusivement sous Windows avec Visual Studio Express pour des raisons de vitesse et de confort. Pour porter mes applications sur les autres plateformes, il me suffit de recopier mes fichiers (sources et données) puis de recompiler avec les outils disponibles (ADT-NDK sous Android, XCode pour iOS et OSX...). Généralement, cela ne me prend que quelques minutes pour faire un portage puisque mon code et mes données sont 100% compatibles sur toutes les plateformes. Pour arriver à ce petit miracle, mon moteur n’utilise que du C++ standard et le plus possible d’API multiplateformes (OpenGL, OpenAL, OpenSL…) ainsi que des librairies C disponible sous forme de code source (pour gérer les format jpg, ogg, zip…). Evidemment, il reste toujours un peu de code spécifique à chaque plateforme (Java, Objective C, DirectX...), mais je le contrains au strict minimum et surtout je ne le mélange pas au code des jeux.

Pour le développement natif sur Android, le NDK compile le code C++ sous forme d’une librairie intégrable au projet Java final grâce à l’interface JNI. La partie Java est extrêmement minime et je ne l'utilise que pour communiquer avec le système. Elle reste donc toujours la même pour toutes mes applications. Il est maintenant possible de faire un projet Android uniquement en C++, mais je ne le recommande pas puisque l’on a souvent besoin d’utiliser des API Java (pour afficher des publicités par exemple).

Sous Android, on peut trouver différents CPU (ARM, Intel x86) mais cela n’a normalement pas d’incidence puisque le langage Java est interprété. Par contre, quand on fait du natif comme moi, on doit compiler pour une architecture spécifique. La majorité des tablettes et téléphones Android ont une architecture ARM. Comme la plupart des développeurs en natif, je ne compilais que pour des architectures ARM (armv5 et armv7). En gros, le NDK compile deux versions distinctes du code, une pour armv5 (pour les anciens appareils Android) et l’autre optimisée pour armv7 (pour les appareils plus récents). C’est géré automatiquement par le système, les APK contiennent deux versions du code et quand l’application est installée, seule la version appropriée est gardée. Les appareils sous architecture x86 ne peuvent pas exécuter du code ARM (évidement puisque ce n'est pas la même architecture). En conséquence, ils doivent interpréter le code ARM via une machine virtuelle. Même si les appareils sous x86 font un superbe job pour interpréter ce code ARM, il est dommage de ne pas utiliser leur puissance maximale. Surtout que c'est extrêmement simple, il suffit de rajouter une troisième cible de compilation. Pour cela, il suffit d’éditer le fichier jni/Application.mk et mettre à jour la variable APP_ABI (c’est elle qui définit les différentes cibles). Puisque je ciblais armv5 et armv7, mon fichier contenait cette ligne :

APP_ABI := armeabi armeabi-v7a

Il m'a suffi de rajouter la variable x86 pour cibler cette troisième architecture :

APP_ABI := armeabi armeabi-v7a x86

A présent, à chaque compilation, une version du code en x86 est aussi ajoutée à mes APK. Quand mes applications sont installées sur un appareil avec architecture Intel, c'est cette nouvelle version qui est conservée. Mes applications tournent donc maintenant à vitesse maximale sur tous les appareils avec CPU x86. Si comme moi vous faites des applications Android en natif (NDK), je recommande l'optimisation x86. C'est tellement simple, il serait dommage de s'en priver.

Personnellement, je n'ai rencontré aucun problème technique car mon moteur est entièrement en C++ standard. J'ai d'ailleurs optimisé toutes mes applications dans la foulée.

Il faut savoir que l’APK gagne un peu en poids, ce qui peut être gênant quand on est proche des 50Mo sur le Google Play.

Si vous utilisez des librairies uniquement compilées pour ARM, vous ne pourrez effectivement plus les utiliser pour les versions x86. C'est pour cela que j'utilise le plus souvent possible des API avec source code disponible.

Si vous avez besoin d'avoir différentes options de compilation par architecture, vous pouvez faire de la compilation conditionnelle dans le fichier Android.mk

ifeq ($(TARGET_ARCH_ABI), x86)

    « Tapez ici la partie du makefile uniquement exécutée lors de la compilation x86 »

endif

A mon avis, pour l’immense majorité des développeurs qui utilisent le NDK comme moi (avec leur propre moteur ou même Cocos2D par exemple), l'optimisation se résumera au simple ajout du mot x86 dans la variable APP_ABI. Vous conviendrez que cela est largement possible en moins de deux minutes. Bonne optimisation à vous tous.

Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.