Quelles optimisations puis-je attendre de Dalvik et de la chaîne d’outils Android?

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?

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:

  • Affectation de registre (8 registres pour la cible v5te car le JIT produit un code de pouce / 16 registres pour v7)
  • Planification (p. Ex. Élimination de ld / st redondante pour les registres Dalvik, levage de charge, naufrage de magasin)
  • Élimination de la vérification par redondance de null (si une telle redondance peut être trouvée dans un bloc de base).
  • Formation de boucles et optimisation pour les boucles simples comptées (c.-à-d. Pas de sortie latérale dans le corps de la boucle). Pour de telles boucles, les access aux tableaux basés sur des variables d’induction étendues sont optimisés, de sorte que les vérifications nulles et à intervalles ne sont effectuées que dans le prolog de boucle.
  • Une entrée en mémoire cache par site virtuel avec application dynamic au moment de l’exécution.
  • Optimisations Peephole comme la réduction de puissance sur les opérandes littéraux pour mul / div.

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.

  1. 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.

  2. 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.

  3. Vérification des limites sur les recherches de tableaux – aucun indice

  4. Valeur ajoutée – Pour autant que je sache, oui – ils seront intégrés dans tous ces scénarios.

  5. Prévision de twig – pas sûr

  6. 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