Question

Je l'ai créé une classe pour gérer mes sorties de débogage pour que je ne ai pas besoin de dépouiller toutes mes sorties du journal avant la sortie.

public class Debug {
    public static void debug( String module, String message) {
        if( Release.DEBUG )
            Log.d(module, message);
    }
}

Après avoir lu une autre question, j'ai appris que le contenu de l'instruction if ne sont pas compilés si la Release.DEBUG constante est fausse.

Ce que je veux savoir est combien les frais généraux est généré en exécutant cette méthode vide? (Une fois que la clause if est supprimée il n'y a pas de code laissé dans la méthode) Est-ce que ça va avoir un impact sur ma demande? Il est évident que la performance est un gros problème lors de l'écriture pour les téléphones mobiles = P

Merci

Gary

Était-ce utile?

La solution

Les mesures effectuées sur Nexus S avec Android 2.3.2:

10^6 iterations of 1000 calls to an empty static void function: 21s  <==> 21ns/call
10^6 iterations of 1000 calls to an empty non-static void function: 65s  <==> 65ns/call

10^6 iterations of 500 calls to an empty static void function: 3.5s  <==> 7ns/call
10^6 iterations of 500 calls to an empty non-static void function: 28s  <==> 56ns/call

10^6 iterations of 100 calls to an empty static void function: 2.4s  <==> 24ns/call
10^6 iterations of 100 calls to an empty non-static void function: 2.9s  <==> 29ns/call

contrôle:

10^6 iterations of an empty loop: 41ms <==> 41ns/iteration
10^7 iterations of an empty loop: 560ms <==> 56ns/iteration
10^9 iterations of an empty loop: 9300ms <==> 9.3ns/iteration

Je l'ai répété plusieurs fois les mesures. Non trouvé des écarts importants. Vous pouvez voir que le coût par appel peut varier considérablement en fonction de la charge de travail (peut-être en raison de la compilation JIT), mais 3 conclusions peuvent être tirées:

  1. Dalvik / java suce à l'optimisation du code mort

  2. appels de fonctions statiques peuvent être optimisés beaucoup mieux que non statique (Fonctions non statiques sont virtuels et doivent être examinées dans une table virtuelle)

  3. le coût sur nexus s ne dépasse pas 70ns / appel (70 cycles des thats ~ cpu) et est comparable au coût d'une vide pour l'itération de boucle (à savoir une augmentation et une vérification de l'état d'une variable locale)

Notez que dans votre cas, l'argument de chaîne sera toujours évaluée. Si vous faites la concaténation de chaîne, cela implique la création de chaînes intermédiaires. Ce sera très coûteux et impliquent beaucoup de gc. Par exemple l'exécution d'une fonction:

void empty(String string){
}

appelé avec des arguments tels que

empty("Hello " + 42 + " this is a string " + count );

10 ^ 4 itérations de 100 ces appels prend 10s. C'est 10US / appel, à savoir ~ 1000 fois plus lent qu'un simple appel vide. Elle produit également énorme quantité d'activité GC. La seule façon d'éviter cela est de la fonction en ligne manuellement, à savoir utiliser la >> << si la déclaration au lieu de l'appel de fonction de débogage. Il est laid, mais la seule façon de rendre le travail il.

Autres conseils

Sauf si vous appelez cela de l'intérieur d'une boucle imbriquée, je ne vous inquiétez pas à ce sujet.

Un bon compilateur supprime toute méthode vide, ce qui ne surcharge pas du tout. Je ne sais pas si le compilateur Dalvik fait déjà, mais je soupçonne qu'il est probable que, au moins depuis l'arrivée du compilateur Just-in-time avec Froyo.

Voir aussi: extension Inline

En termes de performance les frais généraux de production des messages qui sont transmis dans la fonction de débogage vont être beaucoup plus grave, car il est probable qu'ils ne allocations de mémoire, par exemple

Debug.debug(mymodule, "My error message" + myerrorcode);

Ce qui persisteront même à travers le message est mis en cellule. Malheureusement, vous avez vraiment besoin « si (Release.DEBUG) » autour des appels à cette fonction plutôt que l'intérieur de la fonction elle-même si votre objectif est la performance, et vous verrez cela dans beaucoup de code Android.

Ceci est une question intéressante et je l'analyse comme @misiu_mp, donc je pensais que je mettre à jour avec un test 2016 sur un Nexus 7 sous Android 6.0.1. Voici le code de test:

public void runSpeedTest() {
    long startTime;
    long[] times = new long[100000];
    long[] staticTimes = new long[100000];
    for (int i = 0; i < times.length; i++) {
        startTime = System.nanoTime();
        for (int j = 0; j < 1000; j++) {
            emptyMethod();
        }
        times[i] = (System.nanoTime() - startTime) / 1000;
        startTime = System.nanoTime();
        for (int j = 0; j < 1000; j++) {
            emptyStaticMethod();
        }
        staticTimes[i] = (System.nanoTime() - startTime) / 1000;
    }
    int timesSum = 0;
    for (int i = 0; i < times.length; i++) { timesSum += times[i]; Log.d("status", "time," + times[i]); sleep(); }
    int timesStaticSum = 0;
    for (int i = 0; i < times.length; i++) { timesStaticSum += staticTimes[i]; Log.d("status", "statictime," + staticTimes[i]); sleep(); }
    sleep();
    Log.d("status", "final speed = " + (timesSum / times.length));
    Log.d("status", "final static speed = " + (timesStaticSum / times.length));
}

private void sleep() {
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private void emptyMethod() { }
private static void emptyStaticMethod() { }

Le sleep() a été ajouté pour empêcher le tampon de débordement Log.d.

J'ai joué avec elle à plusieurs reprises et les résultats ont été assez conformes à @misiu_mp:

10^5 iterations of 1000 calls to an empty static void function: 29ns/call
10^5 iterations of 1000 calls to an empty non-static void function: 34ns/call

L'appel de la méthode statique a toujours été un peu plus rapide que l'appel de méthode non statique, mais il semble que a) l'écart a diminué de manière significative depuis Android 2.3.2 et b) il y a encore un coût pour faire des appels à une méthode vide , statique ou non.

Regarder un histogramme des temps révèle intéressant quelque chose, cependant. La majorité des appels, que ce soit statique ou non, prendre entre 30-40ns, et en regardant de près les données, ils sont pratiquement tous 30ns exactement.

Exécution du même code avec des boucles vides (commentent les appels de méthode) produit une vitesse moyenne de 8 ns, cependant, environ 3/4 des temps mesurés sont 0ns tandis que les autres sont exactement 30ns.

Je ne sais pas comment expliquer ces données, mais je ne suis pas sûr que les conclusions de @ misiu_mp tiennent encore. La différence entre les méthodes statiques vides et non statiques est négligeable, et la prépondérance des mesures sont exactement 30ns. Cela étant dit, il semble qu'il y ait encore un coût non nul à l'exécution des méthodes vides.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top