Je travaille sur une application Android performante (un jeu), et bien que j’essaie de coder pour la lisibilité en premier, j’aime garder en tête une image de ce qui se passe sous le capot. Avec C ++, j’ai développé une assez bonne intuition sur ce que le compilateur fera et ne fera pas pour moi. J’essaie de faire la même chose pour Java / Android.
D’où cette question. Je n’ai pas trouvé grand chose sur ce sujet sur le web. Le compilateur Java, le convertisseur Dalvik (dx) et / ou JITter (sous Android 2.2+) effectueront-ils les optimisations suivantes?
Méthode inlining. Sous quelles conditions? private
méthodes private
peuvent toujours être intégrées en toute sécurité; Est-ce que cela sera fait? Qu’en est-il public final
méthodes public final
? Méthodes sur des objects d’autres classes? méthodes static
? Que se passe-t-il si le type d’exécution de l’object peut facilement être déduit par le compilateur? Dois-je déclarer les méthodes comme final
ou static
dans static
mesure du possible?
Elimination commune de la sous-expression. Par exemple, si someObject.someField
à someObject.someField
deux fois, la recherche ne sera-t-elle effectuée qu’une seule fois? Et si c’est un appel à un getter? Et si j’utilise une expression arithmétique deux fois? sera-t-il évalué une seule fois? Que se passe-t-il si j’utilise le résultat d’une expression dont je sais que la valeur ne change pas comme la limite supérieure d’une boucle for
?
Vérification des limites sur les recherches de tableau. La chaîne d’outils éliminera-t-elle cela dans certaines conditions, comme l’archétype for
boucle?
Valeur en incrustation. Est-ce que les access à certains public static final int
seront toujours intégrés? Même si ils sont dans une autre classe? Même s’ils sont dans un autre paquet?
Prédiction de twig. Quelle est la taille de ce problème même? L’emtwigment est-il un problème majeur de performance sur un appareil Android typique?
Arithmétique simple Est-ce que someInt * 2
sera remplacé par someInt << 1
?
Etc…
Voici Ben, l’un des ingénieurs travaillant sur le JIT @ Google. Lorsque Bill et moi avons commencé ce projet, l’objective était de fournir un JIT opérationnel dès que possible avec un impact minimal sur les conflits de ressources (par exemple, empreinte mémoire, piratage du processeur par le thread du compilateur). bien. Nous avons donc utilisé un modèle très primitif basé sur les traces. En d’autres termes, l’entité de compilation transmise au compilateur JIT est un bloc de base, parfois aussi court qu’une seule instruction. Ces traces seront assemblées lors de l’exécution via une technique appelée chaînage, de sorte que la recherche de l’interpréteur et du cache de code ne sera pas souvent invoquée. Dans une certaine mesure, la principale source d’accélération réside dans l’élimination de la redondance répétée de l’parsing de l’interpréteur sur les chemins de code fréquemment exécutés.
Cela dit, nous avons quelques optimisations locales mises en œuvre avec le JIT Froyo:
Dans le pain d’épice, nous avons ajouté un revêtement simple pour les getters / setters. Comme l’interface JIT sous-jacente est toujours basée sur des traces, si l’appelé a des twigs, il ne sera pas inséré. Mais le mécanisme de cache en ligne est implémenté afin que les getters / setters virtuels puissent être intégrés sans problème.
Nous travaillons actuellement à élargir la scope de la compilation au-delà d’une simple trace afin que le compilateur dispose d’une fenêtre plus grande pour l’parsing et l’optimisation du code. Restez à l’écoute.
Je suis sûr que ma réponse ne répondra pas à toutes vos questions, mais je suppose que c’est une victoire si elle répond même à une seule.
Vous semblez avoir une connaissance approfondie du sujet et savoir ce que vous voulez pour que vous puissiez faire ce qui suit. Construisez un exemple d’application contenant les aspects sur lesquels vous souhaitez étudier.
Prenez l’APK que vous obtenez et lancez-le via l’ outil APK . Reverse engineering de votre propre code pour faire exactement ce que vous avez l’intention est parfaitement correct, comme nous le soaps.
L’outil APK extraira et décodera vos ressources et procédera au reverse engineering des fichiers .dex
fichiers .smali
. Vous pouvez également rechercher le projet smali pour obtenir plus d’informations sur la lecture des fichiers .smali
et sur ses limitations.
Encore une fois, je suis sûr que cela ne va pas répondre à toutes vos questions, mais cela pourrait être un bon début.
Tout d’abord, permettez-moi de commencer en disant que je ne suis pas un expert en dalvik et que certaines de mes réponses peuvent être fausses. Mais j’ai fouillé dans le code JIT dans dalvik, et je connais bien le bytecode que dalvik exécute.
Méthode inlining – autant que je sache, cela n’arrive jamais. Je suis presque certain que cela ne se produit jamais au niveau du bytecode, et je ne pense pas que cela se produise actuellement au niveau JIT – bien que cela puisse se produire à l’avenir.
Elimination commune des sous-expressions – Je pense que cela ne serait possible que pour les sous-expressions qui n’utilisent pas de variables / champs non finaux. Je ne suis pas tout à fait positif si cela se produirait même alors. Si c’est fait, je m’attendrais à ce que cela se fasse au niveau du bytecode, probablement pas au niveau JIT.
Vérification des limites sur les recherches de tableaux – aucun indice
Valeur ajoutée – Pour autant que je sache, oui – ils seront intégrés dans tous ces scénarios.
Prévision de twig – pas sûr
Arithmétique simple – pas autant que je sache
Aussi, je voudrais mentionner une autre voie d’approche pour vous: dx et dalvik sont tous deux open source, vous pouvez donc les explorer à votre guise. Bien que ce ne soient évidemment pas de petits codes, cela prendrait pas mal de temps pour les creuser à ce niveau