IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

[Perf] Comment optimiser son code ?


Sujet :

Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut [Perf] Comment optimiser son code ?
    Bonjour, pour un projet, je dois réaliser une appli en java analysant une vidéo de visage en temps réel de façon a suivre les contours des yeux et de levres à l'aide de contours actifs.

    J'utilise pour çà le JMF qui me permet de recupérer et d'analyser les frames d'une vidéo très facilement. Malheurement, le JMF est dejà assez gourmand en ressource et j'ai encore plein de calcul a faire derrière !

    En gros, les contours actifs sont basé sur un algo itératif de minimisation de leur énergie et sont ainsi capable de suivre les pixels à gradients elevé d'une frame à l'autre. Mon problème est que j'ai besoin d'un code parfaitement optimisé car chaque milliseconde de calcul compte ici (j'ai environ une cinquantaine de milliseconde de dispo maximum par frame). En gros si mon appli utilise plus que le temps dont elle dispose pour traiter une frame, la frame suivante sera tout simplement ignoré, ce qui a pour effet de sauter des frames et donc d'empécher un suivi de contour efficace.

    C'est pourquoi j'ai besoin de votre aide pour optimiser mon code et essayer de gangner des millisecondes. J'ai quelques questions :

    _ travailler en float ou en double ? j'imagine qu'en float c'est plus rapide puisque c'est coder sur moins d'octets. Maintenant pour graphics2D ou on a le choix ca ne pose pas de problème mais les méthodes de java.lang.Math retourne en général des double. Est ce qu'une conversion de type de style (double) ou (float) et efficace niveau perf ? Et comment eviter la conversion implicite en double ?
    _ J'ai une méthode d'une classe qui est appelé dès que le prog recupère le buffer d'une frame. Vaut il mieux instancier ses objets dans la fonction (donc a chaque appel) ou plutot en global dans la classe pour ne le faire qu'une seule fois et ensuite travailler sur leur contenu ?
    _ L'appel de fonctions ralenti t'elle le code ? Par exemple dans une boucle, vaut il mieux appeler une fonction ou non ? Quitte a perdre en clarté mais gagner en perf.
    _ Enfin le garbage collector est il vraiment optimisé ? Est ce que c'est utile de détruire ses références avec null ou au final ca ne sert pas a grand chose ? Et quand est il de l'appel a finalize() ?
    _ Vaut il mieux créer des variable de type ou bien utiliser directement des methodes ? Par exemple j'ai la fonction getNb() qui me renvoit un nombre entier (ensupposant bien sur que je ne peux pas réunir les 2 boucles en une) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i,a=getNb();
    for(i=0;i<a;i++) {}
    for(i=0;i<a;i++) {}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i;
    for(i=0;i<getNb();i++{}
    for(i=0;i<getNb();i++{}
    Lequel est le plus performant ?

    Voila, désolé pour ce post un peu long mais je suis un peu novice en utilisation mémoire comme java gère tout pour nous et je n'ai pas une très bonne connaissance de la façon dont un compilateur fonctionne. J'espère vous pourrez m'apporter quelques éléments de réponses. Merci
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  2. #2
    Membre averti Avatar de guignol
    Inscrit en
    Mai 2002
    Messages
    309
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 309
    Points : 339
    Points
    339
    Par défaut
    Je vais essayer de répondre à tes questions.

    - float ou double, j'en sais rien
    - Tu instancies les objets une fois pour toute, en global, comme ça tu n'auras pas à le faire à chaque fois.
    - l'appel de fonctions ralentit le caude
    - pour le garbage collecteur, je ne sais pas.
    - POur ta question sur le choix entre variable et appel de fonction (ici getNb()) il vaut mieux appeler la fonction une fois, et utiliser les variables.
    - Fais une recherche, c'est un conseil. Si je me mets à t'aider, tu vas pas t'en sortir

    - "Même avec les yeux grands ouverts, je n'y vois rien".

  3. #3
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Points : 5 943
    Points
    5 943
    Par défaut
    voici un post recent qui pourra peut-être t'aider.
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    652
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2002
    Messages : 652
    Points : 1 151
    Points
    1 151
    Par défaut
    Je ne suis pas un expert en traitement vidéo mais quelques petits conseils et questions en vrac !
    Utilise au maximum le multi-threading.
    Est-ce un traitement bitmap ou vectoriel pour le suivi des contour ?
    Tu parles de temps (50ms) disponible mais quelle puissance (mips) met tu derrière ?
    Je suppose que tu ne doit pas analyser l'ensemble de la trame à chaque nouvelle image ?
    Clic me...
    CV en ligne

    Il y a 10 types de personnes, celui qui connait le binaire, et l'autre...

    Pas de réponse en MP...Merci

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 390
    Points : 432
    Points
    432
    Par défaut
    J'ai découvert récemment un outils qui permet de voir les ressources utilisées par les différentes parties de ton programme.
    Je sais, ceci ne répond pas vraiment à ta question, mais ce genre d'outils peux te permettre de voir les partie de code trop gourmande et qui demande à être optimisées. Moi ca m'a permis de cibler d'ou venait les ralentissement et de les corriger.
    Peut être que dans ton cas ca pourra t'aider à optimiser ton code.
    Si tu utilise Eclipse regarde ici :
    http://eclipsecolorer.sourceforge.ne..._profiler.html

    Pour les autres EDI je n'en connais pas, je sais qu'il en existe pour JBuilder mais payant.

    En seperant que ca puisse t'aider
    ++
    Mess with the best, die like the rest!

  6. #6
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    >travailler en float ou en double ?

    Tu ne verras la différence que si tu fais énormément (plusieurs millions) d'opérations par seconde. En outre si tu dois passer par les casts float/double tu perdras du temps.

    >J'ai une méthode d'une classe qui est appelé dès que le prog recupère le
    >buffer d'une frame. Vaut il mieux instancier ses objets dans la fonction
    >(donc a chaque appel) ou plutot en global dans la classe pour ne le faire
    >qu'une seule fois et ensuite travailler sur leur contenu ?

    Cela dépend de beaucoup de choses, notamment de la taille de tes objets, de leur état, de leur signification pour la classe, etc. En règle générale si tu peux éviter de créer de nouveaux objets, ne te gêne pas.

    >_ L'appel de fonctions ralenti t'elle le code ? Par exemple dans une
    >boucle, vaut il mieux appeler une fonction ou non ? Quitte a perdre en
    >clarté mais gagner en perf.

    Un appel fera forcément perdre du temps. Maintenant les VM modernes comme HotSpot peuvent faire l'inlining à l'exécution donc tu ne peux pas vraiment savoir si ce sera optimisé ou non. Cela dit, le coût d'un appel de méthode est souvent ridicule comparé aux autres optimisations.

    >_ Enfin le garbage collector est il vraiment optimisé ? Est ce que c'est
    >utile de détruire ses références avec null ou au final ca ne sert pas a
    >grand chose ? Et quand est il de l'appel a finalize() ?

    Le GC est très très très optimisé. Jette un oeil à mon article "Know your worst friend, the garbage collector" dans l'édition de mai 2005 du Java Developer's Journal (dispo gratuitement en PDF ici : http://jdj.sys-con.com/general/pdfdownload.htm?issue=610).

    Déréférencer les objets avec null est parfois utile dans le cas de référence croisée qui peuvent provoquer des fuites de mémoire avec le GC. De manière générale cela ne sert pas à grand chose. Enfin, tu ne peux pas prévoir les invocations de finalize() donc n'y touche pas, c'est plus simple

    >_ Vaut il mieux créer des variable de type ou bien utiliser directement
    >des methodes ? Par exemple j'ai la fonction getNb() qui me renvoit un
    >nombre entier (ensupposant bien sur que je ne peux pas réunir les 2
    >boucles en une) :

    Dans ce genre de cas la JVM pourra sûrement optimiser le code à ta place.

    De manière générale les optimisations que tu décris sont les derniers recours. Elles peuvent être efficaces à condition que tout ton code autour soit déjà très optimisé. Dans la plupart des cas tu ne constateras que peu de différences. Il vaut mieux bien connaître les API et leur fonctionnement interne pour savoir comment améliorer les choses (comme l'exemple classique des String et StringBuffer pour la concaténation de chaînes).
    Romain Guy
    Android - Mon livre - Mon blog

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    Merci pour vos quelques réponses.

    Pour répondre à Alwin : Je parle de 50 ms par trame pour une vidéo à 20 image/s ce qui donne 1000/20 soit 50 ms. Et oui je dois analyser chaque pixel de la trame pour chaque nouvelle trame puisque je réalise une detection des bords grace à un masque de Sobel. Alors je dois travailler sur des petites vidéo genre 320*240.
    Pour le traitement, je convertit les donnée d'un buffer frame en tableau d'entier et y applique ensuite un filtre de Sobel. Je desine ensuite mes contours actifs sur un Canvas superposé au visualiseur vidéo avec des méthodes graphiques.
    Je travaille sur 1 athlon 1500+ avec 512Mo de RAM donc ce n'est plus une bete de course aujourd'hui. Vous croyez que sur un PC dernière gen les temps de calculs seraient grandement amélioré ?
    Le problème avec le traitement d'image en temps réel, c'est que ca nécessite enormément de puissance de calcul. J'ai choisi le JMF car il offre des methodes très simples pour manipuler les vidéos mais programmer en natif en C++ par exemple aurait sans doute donner de meilleurs résultats.

    Je n'utilise pas de multithreading. Je laisse le JMF gérer ses frames tranquilement et me base sur cette gestion. A chaque fois qu'un nouveau buffer de frame est envoyer à mon appli grace à un codec que j'ai programmé, la fonction de calcul est appelé. Si elle prend trop de temps la frame suivante sera sautée. En fait je suis obligé d'avoir terminer les calcul pour une frame avant de pouvoir passer à l'autre.

    Pour les float et les double. tu parles de différence au niveau de plusieurs million d'opération par seconde et bien j'arrive a peu près a ce niveau ou du moins a plusieurs centaine de milliers. La majeure partie de l'application repose sur le calcul de fonction mathématique à partir des coordonnées de point. Soit je met ses coordonnée en float et suis obligé de faire une conversion en double pour utiliser les fonctions mathématique de java, soit je stocke tout en double. Je pourrais réécrire les fonction mathématiques dont j'ai besoin pour qu'elle fonctionne en float mais cela me prendrait trop de temps. Donc le mieux serait de tout passer en double pour eviter les conversions de type ?

    Pour l'instanciation d'objet, il me semblait bien que le mieux etait de faire ca même si ca ne parait pas très naturel ni très logique comme prog. Utiliser des variables de classes pour stocker tous les buffers de données que j'utilise uniquement dans une fonction fait bizarre. Sinon utiliser des références d'objet dans une fonction ne pose pas de problème de perf tant qu'il n'y a pas d'instanciation ?

    Pour le garbage collector, il m'arrive en traitant une video d'avoir des freeze à certain moment alors que les calculs sont globalement identiques niveau coût. Je me demandais si ce n'était pas le garbage collector qui saturé et qui devait libérer de la place en urgence. Est ce que les instances utilisé dans les fonctions sont bien déréférencé et pret a etre libéré a la sortie de la fonction ? je pense que oui quand meme.

    Voila. Sinon j'aimerai stocker mes coordonnée de points dans un tableau pour chaque trame. Est ce plus rapide d'utiliser un tableau instancié au début sachant que je connais le nombre total de trames donc sa dimension ou bine utiliser un vecteur avec push est il mieux ?

    Pour GFX, concernant l'utilisation des API, il n'y a pas 36 solutions pour utiliser les classes et méthodes que j'utilise donc j'imagine que mon code est pas mal optimisé au départ. J'utilise très peu les string, en fait juste pour afficher le numéro de la trame traitée, donc l'optimisation de l'utilisation de string est ici négligeable.

    Merci de m'aider en tout cas
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  8. #8
    Membre habitué
    Inscrit en
    Juin 2004
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 165
    Points : 136
    Points
    136
    Par défaut
    Je vois que tu utilises les foctions de Math :

    Réfère toi à ce post (lit directement le dernier message):

    Vérifie que cela est le cas et si ce qui est écrit est vrai alors utilises strictMath qui t'économisera déja l'appel à tes fonctions ...

    Bonne chance et si tu arrives à suffisamment optimiser ton code laisse tous tes "tips" ... il serviront à beaucoup de monde.

  9. #9
    Membre habitué
    Inscrit en
    Juin 2004
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 165
    Points : 136
    Points
    136
    Par défaut
    Euh question bête :

    Est-ce que cela ne serait pas plus rapide de copier le code de certaines classes dans la classe qui les utilise :

    Je m'explique :

    Admettons que dans son code il fait un import java.lang.Math;

    et qu'apres il utilises Math.sqrt(...).

    Est-ce que ca serait pas plus rapide de copier le code de Math (que celui qui l'intéresse dans sa classe et de l'appeler (on économise l'appel à la classe Math mais on grossis le code de la classe principale) ?

  10. #10
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Je doute que tu gagnerais beaucoup en performances en utilisant le C++. La JVM HotSpot est très très bonne pour les opérations de ce genre, c'est à dire du calcul pur. Ce que tu peux sûrement essayer d'optimiser est la phase de dessin mais ce n'est pas sûr, surtout sans voir ton code.

    Puisque tu fais autant d'opérations (j'ai codé moi-même un filtre Sobel avec JMF donc je comprends le problème tu peux faire des micro-benchmarks en utilisant les float puis les doubles. Si tu vois une différence en faveur de l'un ou l'autre, fonce.

    Pour les références dans ton cas tu peux en effet utiliser tes buffers comme membres d'instance plutôt que variables locales.

    Ton problème de garbage collector est très intéressant et je te conseille de te référer à l'article dont j'ai donné l'URL tantôt. J'ai aussi écrit cet article en français en deux parties : http://www.progx.org/index.php?secti...ies&newsid=314 et http://www.progx.org/index.php?secti...ies&newsid=315. Le problème est que tu ne peux pas prévoir quand le GC fera son travail, d'où les freezes. Tu peux tenter, dans ton cas, d'utiliser le GC de HotSpot server en utilisant le flag -server :
    Si tu utilises un tableau tu iras plus vite qu'un vecteur dans tous les cas. Si tu utilies un vecteur n'oublie pas de lui donner une taille par défaut qui lui évitera de grandir (genre new Vector(nbTrames) ou new ArrayList(nbTrames) par exemple).

    Enfin je citais les String comme un exemple mais puisque tu dessines quelque chose à l'écran il y a sûrement des optimisations à faire. Il y a tellement de manières de dessiner une image...
    Romain Guy
    Android - Mon livre - Mon blog

  11. #11
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Citation Envoyé par n00bi
    Euh question bête :
    Est-ce que ca serait pas plus rapide de copier le code de Math (que celui qui l'intéresse dans sa classe et de l'appeler (on économise l'appel à la classe Math mais on grossis le code de la classe principale) ?
    C'est peu probable car la JVM peut faire ce genre d'optimisation en temps réel et elle le fera généralement plus intelligemment que nous puisqu'elle peut adapter l'optimisation au contexte d'exécution.
    Romain Guy
    Android - Mon livre - Mon blog

  12. #12
    Membre habitué
    Inscrit en
    Juin 2004
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 165
    Points : 136
    Points
    136
    Par défaut
    Merci de ta réponse Gfx ... effectivement je pense que ceux qui ont codé la JVM codent mieux que nous ^^

  13. #13
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Ce n'est pas ce que je voulais dire C'est simplement que la JVM dispose de plus d'informations à l'exécution pour réaliser les optimisations. Elle peut ainsi faire des choses impossibles à faire lors de la compilation. C'est d'ailleurs pour cela que javac n'optimise rien pour ainsi dire.

    Mais le fait est qu'HotSpot est un énorme logiciel dont le GC peut être difficile à maîtriser mais ça en vaut la peine.
    Romain Guy
    Android - Mon livre - Mon blog

Discussions similaires

  1. Comment protéger son code du reverse engineering ?
    Par progfou dans le forum Débats sur le développement - Le Best Of
    Réponses: 120
    Dernier message: 12/01/2011, 18h12
  2. comment optimiser son code?
    Par airod dans le forum Débuter
    Réponses: 1
    Dernier message: 28/07/2009, 17h38
  3. comment déboguer son code ?
    Par AdHoc dans le forum Zend
    Réponses: 11
    Dernier message: 05/02/2007, 15h03
  4. comment optimiser son code en calcul ???
    Par gronaze dans le forum C
    Réponses: 5
    Dernier message: 21/03/2006, 10h41
  5. Réponses: 9
    Dernier message: 22/02/2006, 11h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo