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

Langages de programmation Discussion :

Sortie anticipée d'une boucle. "break"


Sujet :

Langages de programmation

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 124
    Points : 86
    Points
    86
    Par défaut Sortie anticipée d'une boucle. "break"
    Bonjour la communauté de developpez.

    Ma question est simple mais je n'ai pas trouvé de réponse sérieuse sur le net.
    L'utilisation d'un "break" est elle judicieuse où faut il privilégier les conditions de sortie dans un while ?

    Exemple en Java avec break :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int val = 9;
    int tab[] = {1, 2, 6, 5, 2, 1, 9, 8, 1, 5};
    int i = 0;
    while (i<tab.lenght()) {
    	if (tab[i] != val) { break; }
    	i++;
    }
    Exemple en Java avec une condition de sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int val = 9;
    int tab[] = {1, 2, 6, 5, 2, 1, 9, 8, 1, 5};
    int i = 0;
    while ((i<tab.lenght()) && (tab[i] != val)) {
    	i++;
    }

  2. #2
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Bonjour,

    Ca va dependre de ton architecture, et de la complexite reelle de ta boucle.

    Dans le cas que tu montres, le code genere doit etre a peu pres pareil ; pour verifier, ecris ce programme en C, et regarde le code assembleur genere.

    Par contre, si tu as un vrai traitement dans ta boucle, ca peut changer un peu. Dans le premier cas, tu as deux tests consecutifs. Donc si on prend un processeur de type Sparc, qui charge les instructions 4 par 4, tu vas pouvoir faire les deux tests en un seul chargement.
    Par contre, si tes deux tests sont "eloignes", cela peut impliquer plus de sauts dans le code assembleur.

    Bien sur, sur une boucle avec 4 occurences, on s'en fou. Je pense ici a des boucles qui seraient appelees des millions de fois ou plus.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 124
    Points : 86
    Points
    86
    Par défaut
    Je vais suivre ton conseil. Je posterai mes conclusions .

  4. #4
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    en dehors de ce qu'a dit gangsoleil, il faut tenir compte aussi de plusieurs choses :

    • Il est possible qu'il y a ait un certain nombre de conditions, certaines ne pouvant être évaluées que à l'intérieur de la boucle..

    • Si le code figurant dans la boucle comporte des algos un tant soit peu complexes, ou pas mal de tests ou de ifs imbriqués, il est plus aisé de faire des "break" que d'ajouter des niveaux d'indentation... Sans compter les gains de temps de tests inutiles...

    • Toutes ces conditions sont également valables pour les "continue" aussi.
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Août 2011
    Messages : 342
    Points : 1 091
    Points
    1 091
    Par défaut
    Tu peux aussi boucler sur un flag. Le flag étant mis à jour par chacun des tests présents dans le corps de ta boucle. Cette solution peut te sauver la vie lorsque tu es en présence d'Ayatollah anti-break

    Edit : je complète ma réponse après avoir étudié plus en détail tes exemples.

    Dans "Clean Code", un bouquin que tu devrais vraiment lire si tu t'intéresses à tout ce qui est approche "propre" du codage, l'auteur suggère de remplacer les tests complexes par des appels de méthodes. Ca a selon lui l'avantage de simplifier la compréhension du code.
    Tu remplaces un test complexe par un appel de méthode avec un nom explicite décrivant le test en question.

  6. #6
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Citation Envoyé par GPPro Voir le message
    Dans "Clean Code", un bouquin que tu devrais vraiment lire si tu t'intéresses à tout ce qui est approche "propre" du codage, l'auteur suggère de remplacer les tests complexes par des appels de méthodes. Ca a selon lui l'avantage de simplifier la compréhension du code.
    Tu remplaces un test complexe par un appel de méthode avec un nom explicite décrivant le test en question.
    Je n'ai pas lu ce livre, et je ne souhaite pas troller dessus, mais pour une boucle appelee des millions de fois (boucle infinie de serveur, ...), un appel de methode n'a pas du tout le meme cout que le teste d'une variable.

    En gros, pour tester une valeur, on charge la valeur dans un registre, on charge la valeur attendue dans un autre, et on regarde si les deux ont la meme valeur. Et si la valeur testee est 0, il n'y a pas besoin du second chargement, car 0 est souvent stockee dans un registre "en dur" sur pas mal d'architectures.

    Un appel de methode, c'est beaucoup plus complexe, puisqu'outre la modification des registres, on va modifier le pointeur d'appel -- au grand minimum.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  7. #7
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Août 2011
    Messages : 342
    Points : 1 091
    Points
    1 091
    Par défaut
    Citation Envoyé par gangsoleil Voir le message
    Je n'ai pas lu ce livre, et je ne souhaite pas troller dessus, mais pour une boucle appelee des millions de fois (boucle infinie de serveur, ...), un appel de methode n'a pas du tout le meme cout que le teste d'une variable.

    En gros, pour tester une valeur, on charge la valeur dans un registre, on charge la valeur attendue dans un autre, et on regarde si les deux ont la meme valeur. Et si la valeur testee est 0, il n'y a pas besoin du second chargement, car 0 est souvent stockee dans un registre "en dur" sur pas mal d'architectures.

    Un appel de methode, c'est beaucoup plus complexe, puisqu'outre la modification des registres, on va modifier le pointeur d'appel -- au grand minimum.
    Je m'attendais à ce genre de réponse, vraiment bizarre... Ou comment rejeter un principe générique au nom d'une optimisation pour un cas particulier.

    Ca c'est pour la forme.

    Sur le fond : j'ai parlé de tests complexes, merci de bien lire...

  8. #8
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Citation Envoyé par GPPro Voir le message
    Je m'attendais à ce genre de réponse, vraiment bizarre... Ou comment rejeter un principe générique au nom d'une optimisation pour un cas particulier.
    Le sujet parle de savoir si un break dans un while est mieux ou pire qu'un test dans le while.
    A mon sens, on est ici dans des optimisations tres fines, pas dans des cas bourrins ou il y a 42 parametres differents a interpoler avant de connaitre la valeur a tester.

    Et ce cas d'optimisation fines, tu vois cela comme un cas particulier, moi c'est mon quotidien. Donc non, ce n'est pas forcement un cas particulier. Et comme on n'a pas le contexte, on ne sait pas qui de nous deux a raison, si tant est que l'un de nous deux soit plus proche du contexte du posteur que l'autre, ce qui n'est pas certain du tout.

    Sur le fond : j'ai parlé de tests complexes, merci de bien lire...
    C'est quoi un test complexe ? Dans les exemples ici, on a la longueur d'un tableau, et l'acces au contenu d'une cellule.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  9. #9
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Citation Envoyé par gangsoleil Voir le message
    A mon sens, on est ici dans des optimisations tres fines, pas dans des cas bourrins ou il y a 42 parametres differents a interpoler avant de connaitre la valeur a tester.
    Et même dans ce cas-là, quand on boucle sur suffisament d'éléments, un appel de méthode se fait très nettement ressentir et peut être un facteur d'optimisation intéressant (même si c'est au détriment d'un peu de lisibilité dans le code).

    Et c'est d'autant plus vrai dans les langages Objet qui permettent la surcharge des méthodes.

  10. #10
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Août 2011
    Messages : 342
    Points : 1 091
    Points
    1 091
    Par défaut
    Citation Envoyé par Loceka Voir le message
    Et même dans ce cas-là, quand on boucle sur suffisament d'éléments, un appel de méthode se fait très nettement ressentir et peut être un facteur d'optimisation intéressant (même si c'est au détriment d'un peu de lisibilité dans le code).

    Et c'est d'autant plus vrai dans les langages Objet qui permettent la surcharge des méthodes.
    Et on inventa le mot clé "inline", les macros, etc... Si vraiment vous voulez jouer au jeu des optimisations à tout prix, il y a des outils pour ça, mais bref, ce débat est à la limite du trolling.

  11. #11
    Expert éminent sénior
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    6 803
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 6 803
    Points : 32 058
    Points
    32 058
    Par défaut
    Réponse d'ingénieur : ça dépend.

    (mais là, je ne fais que résumer ce qui précède).

    La première chose à faire, c'est de se renseigner sur les normes de là ou tu codes. certains banniront le break ou le goto, d'autre l'autoriseront sous conditions. J'ai par exemple vu une boite ou le seul GO TO autorisé était le GO TO finDeParagraphe. une espèce de break façon cobol, quoi.

    (1)Si le break est autorisé, et systématiquement utilisé, la réponse est simple : à Rome comme les Romains.

    (2)Si le Break est interdit, la réponse est tout aussi simple : à Florence comme les Florentins.

    (3)Si le break est autorisé, mais pas systématiquement utilisé, là, il faut faire preuve d'analyse.
    ==>Dans ce cas précis, je dirais que la boucle a pour seul objet d'arriver à sa condition de sortie; il me parait donc judicieux de garder la condition de sortie explicite dans la boucle elle-même, donc de ne pas mettre de break.
    ==>Dans le cas le plus fréquent(enfin, dans mon monde), qui est celui d'avoir une boucle qui fait des choses à chaque itération, en plus de vérifier les conditions de sortie, rajouter un break quand on arrive prématurément à un niveau ou on a plus besoin de boucler me parait plus "léger" que d'encombrer la condition de sortie.

    Mais c'est juste une question de point de vue perso. Il y aura sans doute des avis divergents. Le plus important, c'est de respecter le style local. Mieux vaut un mauvais style uniformément utilisé, qu'un mélange de bons styles incompatibles(cette dernière phrase va sans doute me valoir des -1. Mais je parle d'expérience sur des codes de 36 ans d'âge).
    Les 4 règles d'airain du développement informatique sont, d'après Michael C. Kasten :
    1)on ne peut pas établir un chiffrage tant qu'on a pas finalisé la conception
    2)on ne peut pas finaliser la conception tant qu'on a pas complètement compris toutes les exigences
    3)le temps de comprendre toutes les exigences, le projet est terminé
    4)le temps de terminer le projet, les exigences ont changé
    Et le serment de non-allégiance :
    Je promets de n’exclure aucune idée sur la base de sa source mais de donner toute la considération nécessaire aux idées de toutes les écoles ou lignes de pensées afin de trouver celle qui est la mieux adaptée à une situation donnée.

  12. #12
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par GPPro Voir le message
    Tu remplaces un test complexe par un appel de méthode avec un nom explicite décrivant le test en question.
    Citation Envoyé par GPPro Voir le message
    Sur le fond : j'ai parlé de tests complexes, merci de bien lire...
    Je crois que l'on dévie, ou que la question initiale n'est pas très claire..

    La règle de conduite à tenir pour les boucles, ou les while().. est d'avoir une condition simple..

    Si la condition est complexe, c'est qu'il y a un problème d'analyse...

    Des tests complexes ne dovent pas exister pour une boucle ..

    Si c'était le cas, c'est sûr que l'appel à une méthode serait bien mieux. Cependant le fond est conceptuellement incorrect...


    Maintenant, le problème du "break" est entièrement différent de la condition.. Et toalement différent également du goto


    • Le goto termine nécesairement par du code spaghetti... peut être utilisé à diverses sauces, et dans 99.99% des cas ne se justifie pas..

    • le break est une manière simple et rapide de terminer une boucle, point final (comme le "continue" est une manière simple et rapide de sauter un élément).



    Citation Envoyé par el_slapper Voir le message
    (3)Si le break est autorisé, mais pas systématiquement utilisé, là, il faut faire preuve d'analyse.
    ==>Dans le cas le plus fréquent(enfin, dans mon monde), qui est celui d'avoir une boucle qui fait des choses à chaque itération, en plus de vérifier les conditions de sortie, rajouter un break quand on arrive prématurément à un niveau ou on a plus besoin de boucler me parait plus "léger" que d'encombrer la condition de sortie.
    Totalement d'accord...

    Le fond du problème n'est pas que les conditions puissent être complexes, c'est que le code peut le devenir, avec des séries de ifs imbriqués...

    Ajouter un "break" ou un "continue" simplifie et le code et la pensée et l'éxécution : on peut boucler jusqu'à une certaine limite, sauter des éléments dans certains cas, sortir dans d'autres, et c'est clair et lisible.. Faire une condition complexe est lourd, incompréhensible, peu souple, et peu efficace en termes d'optimisation justement...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 124
    Points : 86
    Points
    86
    Par défaut
    Je n'ai pas eu le temps de faire une analyse du code assembleur comme je voulais faire. En ce moment je n'ai vraiment pas le temps...

    Ma question n'était pas assez claire, je confirme.

    A l'origine je m'intéressais uniquement à la performance du code. Les exemples de code que je donne ne sont pas significatifs. C'était pour me faire comprendre. Et, avec des continus ou des breaks, peut importe, le problème reste le même je pense.

    En terme d'efficacité pure, j'ai toujours imaginé que de mettre des breaks était un peu pénalisant. Mais, avec des codes qui ont de nombreux if, while... imbriqués, comme les automates notamment, ça devient très vite fastidieux et en plus on obtient un code vraiment illisible. C'est pour ça que je pose cette question sur la perte d'efficacité du code lorsqu'on utilise des breaks ou des continus.

    Pour participer au débat, je pense que si la rapidité du code n'est pas primordial il ne faut pas se priver des breaks, voir même il faut les utiliser, car avec on programme plus vite et un code plus clair. Les GO TO, c'est un autre problème, c'est une source d'erreur.

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 124
    Points : 86
    Points
    86
    Par défaut
    Par ailleurs plutôt que de faire une analyse du code assembleur généré, j'essaierai de faire des codes représentatifs, avec et sans breaks. Sur des boucles relativement longues je comparerai leurs temps d'exécution.

    Après il faut que je trouve les codes qui seront représentatifs.

    A suivre...

  15. #15
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Ahhhhhhhh .. Encore un qui veut optimiser en tentant d'optimiser des ifs et des breaks !!!!!!!

    Disons que si c'est dans un but d'optimisation, il y a bien d'autres choses à optimiser avant ça...

    Ne serait-ce que dans ton exemple..

    Tab[i] représente une addition et une multiplication par élément i : i*taille+offset

    Si tu utilises un pointeur, tu réduis à 1 addition par élément, tu économises donc N multiplications dans ta boucle...

    C'est très nettement plus optimisant que de vouloir optimiser des ifs ou des breaks...

    De manière primordiale, c'est l'algo qui doit être optimisé.

    Ensuite, le genre de ce que je mentionne : utilisation de pointeurs pour enlever les calculs d'adressage; factorisation de ce qui peut l'être aux niveaux supérieurs, etc etc..

    L'optimisation des ifs et breaks arrivent en toute toute toute dernière position, et n'a qu'un impact purement négligeable par rapport au reste.. Les CPU, et es compilateurs, font un boulot quasi-parfait de ce côté là... Tu peux toujours tenter, mais tu ne gagneras rien.. C'est dans le reste que tu gagnes..
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  16. #16
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Août 2011
    Messages : 342
    Points : 1 091
    Points
    1 091
    Par défaut
    De plus, la dernière fois que je me suis intéressé à la question, et c'était y'a longtemps hein, parcourir un tableau ça se faisait avec un for (d'un point de vue perf, vous jetez pas sur le -1)...
    Les compilos savent optimiser for + tableau, while + tableau je ne pense pas.

    De même, pour le coup je ne pense pas que les compilateurs sachent optimiser convenablement les boucles contenant des instructions de rupture de flot. De même pour les processeurs actuels d'ailleurs.

Discussions similaires

  1. sortie anticipé d'une procédure
    Par patou41000 dans le forum C++/CLI
    Réponses: 2
    Dernier message: 30/04/2007, 10h09

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