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

Windows Forms Discussion :

[C# 1.1]Boucles foreach imbriquees


Sujet :

Windows Forms

  1. #1
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut [C# 1.1]Boucles foreach imbriquees
    Bonjour a tous,

    j'ai une collection que je conserve en cache dans mon appli, ca m'evite d'aller reinterroger ma BD embarquee.
    Cette collection contient des noms d'organismes (avec tous les parametres associes):je dois verifier parmi les differentes adresses de ces organismes (donc une autre collection) lesquelles appartiennent a une region donnee (identifiee par identifiantRegion._id).
    J'ai donc les classes suivantes: organisme, adresse, ville, departement et region.

    Voila le code que j'utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    foreach(IOrganisme iorganisme in CollectionOrganismes)
    {	
    	foreach (IAdresse iadresse in iorganisme._adresseCollection)
    	{
    		if (iadresse._ville._departement._region._id.Equals(identifiantRegion._id))
    			{
    				ListViewItem lvi = new ListViewItem();
    				lvi.Tag = iorga;
    				lvi.Text = iorga._nom ;
    				MaListViewAMoi.Items.Add(lvi);
    			}
     
    	}
    }
    Les performances sont bien evidemment desastreuses, mais je ne vois pas comment faire autrement qu'en passant par ces boucles imbriquees. Voyez vous un moyen d'ameliorer tout ca?

  2. #2
    Membre éprouvé
    Avatar de HULK
    Inscrit en
    Juillet 2003
    Messages
    1 273
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 273
    Points : 1 280
    Points
    1 280
    Par défaut
    bah tu peux pas refaire une requete sur ta base ???
    j'suis vert !

  3. #3
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut
    Citation Envoyé par HULK
    bah tu peux pas refaire une requete sur ta base ???
    Si bien sur, et c'etait la ma premiere facon de faire; mais les performances ne sont pas au rendez vous; je travaille sur une base cryptee, la decrypter prend du temps et c'est pour cette raison que je voulais effectuer ma recherche sur les donnees deja sortie et presente en cache.

  4. #4
    Membre émérite
    Avatar de Merlin
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2002
    Messages
    524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mars 2002
    Messages : 524
    Points : 2 883
    Points
    2 883
    Par défaut Re: [C# 1.1]Boucles foreach imbriquees
    Citation Envoyé par Nip
    Les performances sont bien evidemment desastreuses, mais je ne vois pas comment faire autrement qu'en passant par ces boucles imbriquees. Voyez vous un moyen d'ameliorer tout ca?
    tout dépend de la longueur de tes listes, mais il est clair que le traitement peu être long.
    Ce bon Niklaus Wirth, père du Pascal, nous a enseigné dans son ouvrage "Algorithms + Data Structures = Programs" une chose essentielle : les structures de données sont aussi importantes que les algos...
    Et dans le cas de ta recherche, à la fois l'algo et la structure de données ne sont pas adaptées tout simplement :-)

    Si tes listes sont grandes, ce qui semble être le cas si tu parles de traitements longs, plutôt que des collections d'interfaces, il serait plus sage d'utiliser des listes hashées sur le champ ID comme clé par exemple.
    Ou tout autre structure clé/valeur utilisant un système de tri et une recherche dichotomique ou un arbre binaire.
    Ta recherche deviendra instantanée...

  5. #5
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut
    Mes collections ne sont pas si importantes puisque pour cet exemple il y a seulement 2000 valeurs. Mais la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (iadresse._ville._departement._region._id.Equals(identifiantRegion._id))
    prend reellement beaucoup de temps; de toute facon meme sans cette ligne les 2 foreach imbriques entrainent un traitement trop long

    Je vais regarder du cote des listes hashees et je vous tiens au courant, merci Merlin

  6. #6
    DrQ
    DrQ est déconnecté
    Membre expérimenté
    Avatar de DrQ
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    388
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 388
    Points : 1 515
    Points
    1 515
    Par défaut
    Qu'appelles tu prendre du temps ?? J'utilise des algos avec environ 2000 lignes qui en moins d'une seconde filtre et tri le résultat souhaité et ce toutes les secondes et avec rafraichissement de l'UI.
    Donc je suis surpris que ça soit si long que ça !!!
    Est ce que tes collections évoluent ? Si oui peuvent elles évoluées pendant leur parcours ? Fais tu des lock sur tes collections ?

    Pour des raisons de perfs pures, un for simple sera peut être un peu plus adéquat.
    1)http://www.developpez.com/cours/
    2)Recherche
    3)Posez votre question en suivant les règles
    _oOo-DrQ-oOo_

  7. #7
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut
    Citation Envoyé par DrQ
    Qu'appelles tu prendre du temps ?? J'utilise des algos avec environ 2000 lignes qui en moins d'une seconde filtre et tri le résultat souhaité et ce toutes les secondes et avec rafraichissement de l'UI.
    Je parle de 1 seconde pour la simple manipulation de la liste (juste apres le premier foreach) mais de plus de 2 minutes des le passage dans le deuxieme foreach(c'est le point critique) et pres de 4 minutes en executant la sequence complete.

    Citation Envoyé par DrQ
    Est ce que tes collections évoluent ? Si oui peuvent elles évoluées pendant leur parcours ? Fais tu des lock sur tes collections ?
    mes collections ne bougent pas et sont tirees de mon singleton

  8. #8
    Membre régulier
    Inscrit en
    Juillet 2005
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 83
    Points : 100
    Points
    100
    Par défaut
    Quelques pistes :
    • Teste ce code:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      foreach(IOrganisme iorganisme in CollectionOrganismes) 
      {    
         foreach (IAdresse iadresse in iorganisme._adresseCollection) 
         { 
            if (iadresse._ville._departement._region._id.Equals(identifiantRegion._id)) 
               { 
                  ListViewItem lvi = new ListViewItem(); 
                  lvi.Tag = iorga; 
                  lvi.Text = iorga._nom ; 
                  // MaListViewAMoi.Items.Add(lvi); 
               } 
       
         } 
      }
      Si le traitement est beaucoup plus rapide, alors c'est le peuplement de ta ListView qui est en cause. Je te conseille dans ce cas de jeter un oeil à la section "Control Population" de cet article.
    • Plutôt qu'utiliser des foreach dont certes la syntaxe est sympathique, implémente des IEnumerators. Si mes souvenirs sont exacts, sous le framework 1.1 les énumérateurs utilisés par l'instruction foreach sont des classes au lieu d'être des struct, ce qui a un impact négatif sur les performances.
    • Est-ce que tes ID sont des entiers ? Si ce sont des strings, alors tu devrais t'efforcer d'utiliser des entiers (la comparaison est bcp plus rapide).

  9. #9
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut
    Salut Wyatan, merci pour tes remarques

    Citation Envoyé par Wyatan
    Si le traitement est beaucoup plus rapide, alors c'est le peuplement de ta ListView qui est en cause. Je te conseille dans ce cas de jeter un oeil à la section "Control Population" de cet article.
    Aucune difference de performances a ce niveau; mais je n'avais pas lu l'article, tres instructif

    Citation Envoyé par Wyatan
    Plutôt qu'utiliser des foreach dont certes la syntaxe est sympathique, implémente des IEnumerators. Si mes souvenirs sont exacts, sous le framework 1.1 les énumérateurs utilisés par l'instruction foreach sont des classes au lieu d'être des struct, ce qui a un impact négatif sur les performances.
    Je vais reagrder aussi de ce cote, merci

    Citation Envoyé par Wyatan
    Est-ce que tes ID sont des entiers ? Si ce sont des strings, alors tu devrais t'efforcer d'utiliser des entiers (la comparaison est bcp plus rapide).
    De ce cote, malheureusement, je n'y touche pas, les ID sont des GUID et pris en charge par mon outil de mapping OR.

  10. #10
    Membre régulier
    Inscrit en
    Juillet 2005
    Messages
    83
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 83
    Points : 100
    Points
    100
    Par défaut
    Une autre piste pourrait être de rendre ton modèle de données moins "puriste", justement pour des raisons de performances : intègre à chaque adresse directement les identifiants du département et de la région à laquelle elle appartient.

    Au fait, si un organisme dispose de plusieurs adresses dans une même région, il apparaîtra plusieurs fois dans ta liste. Ne devrais-tu pas ajouter un break à la fin de ton bloc conditionnel pour éviter ces doublons (et quelques boucles inutiles) ?

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2005
    Messages : 144
    Points : 94
    Points
    94
    Par défaut
    Tu pourrrais peut-être modifier ton code afin de mettre tes éléments dans une table de hashage...

  12. #12
    DrQ
    DrQ est déconnecté
    Membre expérimenté
    Avatar de DrQ
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    388
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 388
    Points : 1 515
    Points
    1 515
    Par défaut
    Cela prendrait un peu plus de mémoire, mais ne serait pas plus d'avoir tes à plat en mémoire (résultat d'une requête avec les jointures entre toutes les tables) ?

    Si c'est l'utilisation mémoire que tu ne veux pas trop utilsé (même si tu fais 2000 lignes * 1024 octets (tout confondu), ça ne fait que 2Mo de données en mémoire), tu peux construire tes objets différemment.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    public class Address
    {
      private string _strAddress1;
      private string _strAddress2;
      private string _strCity;
      private string _strCodePostal;
      ...
    }
     
    public class Organisme
    {
      // Liste des adresses
      private ArrayList _oArrayListAddresses = null;
      // Adresse par défaut
      Address _oAddressDefault = null;
      // Nom de l'organisme
      private string _strName;
     
     
      public void AddAddress(Address oAddress)
      {
        _oArrayListAddresses.Add(oAddress);
      }
     
      public void SetDefaultAddress(Address oAddress)
      {
        _oAddressDefault = oAddress;
      }
    }
    Biensûr après faut créer les accesseurs nécessaires.
    Si en mémoire tu stockes déjà de cette façon tu gagneras un temps conséquent.

    Rien ne t'empêche d'avoir une collection d'adresses, de ville, de région séparées, mais en mémoire de toute façon ce sont des pointeurs que tu auras sauf si tu souhaites garder la donnée indépendemment de tes collections dans quel tu devras faire une copie de tes objets.
    1)http://www.developpez.com/cours/
    2)Recherche
    3)Posez votre question en suivant les règles
    _oOo-DrQ-oOo_

  13. #13
    Nip
    Nip est déconnecté
    Rédacteur

    Inscrit en
    Juin 2004
    Messages
    963
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 963
    Points : 1 076
    Points
    1 076
    Par défaut
    Voila j'ai pu travailler dessus hier et ca marche niquel .
    J'ai fait le choix de la hashtable et je dois avouer que les perfs sont extremements satisfaisantes: 2 secondes au lieu des 4 minutes precedemments annoncees.
    Par ailleurs je me suis servi de Build a C# DictionaryHashList Collection Object qui me permet de gerer mes collections d'objet de facon efficace.

    Je n'ai pas eu le temps de regarder ta solution DrQ, mais je ne veux pas toucher a mes classes. Peut etre en modifiant les interfaces, je regarderai plus tard, merci.

    Maintenant un autre probleme se pose puisque mon appli mets pres de 3 minutes a se lancer, le temps de peupler ma Hashtable. Je regarde ca et si je ne peux pas le resoudre je reviens vers vous.
    Ce probleme est resolu, merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 18
    Dernier message: 25/07/2007, 12h34
  2. [JSTL] boucle forEach pour deux liste en même temps
    Par ruud002 dans le forum Taglibs
    Réponses: 1
    Dernier message: 28/09/2006, 15h54
  3. [Tableaux] Boucle foreach inbriquée
    Par nebil dans le forum Langage
    Réponses: 17
    Dernier message: 10/09/2006, 11h40
  4. [C# VS 2005] Collection et boucle foreach
    Par SDragon dans le forum Windows Forms
    Réponses: 3
    Dernier message: 24/07/2006, 19h43
  5. [Tableaux] la boucle foreach
    Par jeanfrancois dans le forum Langage
    Réponses: 7
    Dernier message: 09/03/2006, 17h29

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