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 :

Garder dans la mémoire les calculs des fonctions


Sujet :

Java

  1. #1
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut Garder dans la mémoire les calculs des fonctions
    Bonjour,

    Je suis entrain de faire des calculs avec des fonctions en java et je voudrais que les calculs que je vais se conservent dans la mémoire pour que lorsque je voudrais relancer le calcul de la même fonction avec les mêmes paramètres, il ne refait pas les même calculs mais l'extrait simplement de la mémoire ca devient plus rapide et plus ergonomique Y'a-t-il un moyen pour faire ceci ?!
    Merci

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    il faut faire ce genre de mise en cache vous même, par exemple au début de la méthodes.

  3. #3
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    il faut faire ce genre de mise en cache vous même, par exemple au début de la méthodes.
    je vois pas très bien comment faire !! Pourrais tu m'éclaircir s'il te plait ..

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Ben tu stocke dans une cache quelconque (une Map par exemple) les résultats des différentes calculs déjà effectué et avant de faire un calcul tu vérifie si il y a pas déjà la réponse dans la Map.

  5. #5
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Ben tu stocke dans une cache quelconque (une Map par exemple) les résultats des différentes calculs déjà effectué et avant de faire un calcul tu vérifie si il y a pas déjà la réponse dans la Map.
    à ce que j'ai bien compris, je déclare une variable bouléenne cacheOK et une variable cacheData et puis, je fais un code de genre :

    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
     
    public List loadAll(Connection conn) throws SQLException, NotFoundException {
     
              // Check the cache status and use Cache if possible.
              if (cacheOk) {
                  return cacheData;
              }
     
              String sql = "SELECT * FROM Table";
              List searchResults = listQuery(conn, conn.prepareStatement(sql));
     
              // Update cache and mark it ready.
              cacheData = searchResults;
              cacheOk = true;
     
              return searchResults;
        }
    ca marche oui, mais seulement pour des requêtes statiques qui renvoient toujours le même résultat, par contre, les résultats obtenus sont variables en fonction des paramètres que j'intègre dans ma requête c'est pour ca que si j'utilise ce genre de cache, je me retrouverai en état de retourner le meme calcul pour différents paramètres, ce qui ne me correspond pas à mes besoins y'a-t-il un moyen pour le faire ?

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    tu met simplement l'ensemble de tes paramètre en clé de ta Map

  7. #7
    Modérateur

    Avatar de Robin56
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juin 2009
    Messages
    5 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Juin 2009
    Messages : 5 297
    Par défaut
    Citation Envoyé par ROUGE87 Voir le message
    ca marche oui, mais seulement pour des requêtes statiques qui renvoient toujours le même résultat, par contre, les résultats obtenus sont variables en fonction des paramètres que j'intègre dans ma requête c'est pour ca que si j'utilise ce genre de cache, je me retrouverai en état de retourner le meme calcul pour différents paramètres, ce qui ne me correspond pas à mes besoins y'a-t-il un moyen pour le faire ?
    C'est totalement normal qu'il y ait ce genre de comportement.

    L'idée c'est de sauvegarder tes paramètres et le résultat dans une HashMap par exemple :
    1. Tu calcules le résultat Y pour le paramètre X
    2. Tu ajoutes une entrée dans ta HashMap : tonHashMap.put(X, Y);
    3. Lors de la prochaine exécution de ta fonction, tu dois calculer le résultat pour le paramètre X' :
    - Tu vérifies si tonHashMap.get(X') renvoie quelquechose
    - Elle ne renvoie rien, tu peux refaire le calcul et ajouter dans ta HashMap tonHashMap.put(X', Y')
    4. Lors d'une nouvelle exécution de ta fonction, tu dois calculer le résultat pour le paramètre X de nouveau :
    - tonHashMap.get(X) te renvoie alors Y, tu sais alors qu'il n'y a pas besoin de le re-calculer
    5. Etc, etc ...
    Responsable Java de Developpez.com (Twitter et Facebook)
    Besoin d'un article/tutoriel/cours sur Java, consulter la page cours
    N'hésitez pas à consulter la FAQ Java et à poser vos questions sur les forums d'entraide Java
    --------
    Architecte Solution
    LinkedIn : https://www.linkedin.com/in/nicolascaudard/

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Attention quand même que suivant les calculs, ce n'est pas une mince affaire de gérer la Map car il faudra à un moment ou un autre à penser à la vider de ses plus ancien résultat sous peine de bouffer toute la mémoire de la JVM à plus ou moins long terme


    A ce titre, la classe LRUMap de commons-collections est très pratique, elle évince automatiquement le clés les plus anciennes

  9. #9
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par Robin56 Voir le message
    C'est totalement normal qu'il y ait ce genre de comportement.

    L'idée c'est de sauvegarder tes paramètres et le résultat dans une HashMap par exemple :
    1. Tu calcules le résultat Y pour le paramètre X
    2. Tu ajoutes une entrée dans ta HashMap : tonHashMap.put(X, Y);
    3. Lors de la prochaine exécution de ta fonction, tu dois calculer le résultat pour le paramètre X' :
    - Tu vérifies si tonHashMap.get(X') renvoie quelquechose
    - Elle ne renvoie rien, tu peux refaire le calcul et ajouter dans ta HashMap tonHashMap.put(X', Y')
    4. Lors d'une nouvelle exécution de ta fonction, tu dois calculer le résultat pour le paramètre X de nouveau :
    - tonHashMap.get(X) te renvoie alors Y, tu sais alors qu'il n'y a pas besoin de le re-calculer
    5. Etc, etc ...
    j'ai bien saisi l'idée, elle me convient parfaitement seulement, pour moi, le résultat Y n'est pas pour un seul paramètre X mais plutot de deux paramètres X1 et X2 !! c'est pour ca que j'ai pensé à faire une liste qui contient X1 et X2, je ne vois pas un autre moyen seulement, tant que je déclare ma liste en new ArrayList(), il ne conserverai rien dans la mémoire, enfin, je pense..
    Citation Envoyé par tchize_ Voir le message
    Attention quand même que suivant les calculs, ce n'est pas une mince affaire de gérer la Map car il faudra à un moment ou un autre à penser à la vider de ses plus ancien résultat sous peine de bouffer toute la mémoire de la JVM à plus ou moins long terme


    A ce titre, la classe LRUMap de commons-collections est très pratique, elle évince automatiquement le clés les plus anciennes
    oui très bien, j'ai travaillé avec LRUMap mais comme je viens de l'expliquer, je n'ai pas trouvé le moyen de conserver la liste que j'ajoute.
    PS: j'ai conclu tout seul que ca ne conserve pas dans la mémoire car le temps d'exécution est le meme, autant à la première qu'à la deuxième exécution.
    Voici mon code, ca pourrait etre plus explicite qu'une bonne explication :

    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
    31
    32
    33
    34
    35
    36
    37
     
        private static  LRUMap Map = new LRUMap() ;
        private static ArrayList list = new ArrayList();
     
    public static double loadSelectedval(Connection conn, int val, String mot) throws SQLException, NotFoundException {
     
    			list.add(id_edge);
                list.add(dateString);
                double d ;
                if (Map.get(list) != null){
                    d = Double.parseDouble(Map.get(list).toString());
                    return d;
                }
            String sql = "SELECT A.charge FROM A "
    	  +"	WHERE A.valeur = ? AND A.mot = ?";
     
     
            PreparedStatement stmt = null;
            ResultSet result = null;
            double cumulTS = 0 ;
              try {
                       stmt = (PreparedStatement) conn.prepareStatement(sql);
                       stmt.setInt(1, val);
                       stmt.setString(2, mot);
                               result = stmt.executeQuery();
                               double temp;
                               while (result.next()) {
                                temp = result.getDouble("charge");
                                cumulTS = cumulTS + temp;
                              }
    						Map.put(list, (double) cumulTS);
                            return cumulTS;
              } finally {
                  if (stmt != null)
                      stmt.close();
              }
        }

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    y a plein d'erreurs:

    d'abord, je ne sais pas si c'est voulu, mais ta clé tu lui met des valeur qui n'ont rien à voir avec la fonction (tu lui met id_edge et datestring alors qu'on cherche val et mot)
    ensuite, une list est une mauvais clé pour un Map, la Map exige que la clé soit immutable. Bon on peux garder une liste, mais faut pas la changer après l'avir mise en clé alors.
    enfin, a chaque appel, tu rajoute des valeur dans la même liste, alors que normalement tu devrais avoir une nouvelle liste à chaque fois. En effet, actuellement tu fait cecil
    List = [id_edge,datestring], calcul, ajout dans la map
    ensuite deuxième appel
    List = [id_edge,datestring,id_edge,datestring], existe pas dans la map, recalcul, ajout
    ensuite troisième appel
    List = [id_edge,datestring,id_edge,datestring,id_edge,datestring], existe pas dans la map, recalcul, ajout
    etc etc


    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
        private static  LRUMap Map = new LRUMap() ;
     
     
    public static double loadSelectedval(Connection conn, int val, String mot) throws SQLException, NotFoundException {
     
                List list = new ArrayList<Object>();      
                list.add(val);
                list.add(mot);
                list = Collections.unmodifiableList(list); // pour éviter les emmerdes
                if (!Map.contains(list)){
                    .... calcul de reslutat, de type double
                    map.put(list,resultat); // et stockage
                }
                return (Double)map.get(list);
           }

  11. #11
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Euhhh, là tu n'as qu'une seule liste statique qui va donc contenir tous les paramètres déjà passés !

    Je te conseille de faire une classe dédiée ...

    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
    31
     
    public class ParametresAppelProc {
     
       public ParametresAppelProc(String nomProc, List<Object> listParam) {
         this.nomProc = nomProc;
         this.listParam = listParam;
       }
     
       private String nomProc;
     
       private List<Object> listParam;
     
     
       public int hashCode() {
    	   int hash = 17;
    	   hash += nomProc.hashCode();
    	   hash += (listParam != null) ? listParam.hashCode() : 0;
    	   return hash;
       }
     
       public boolean equals(Object other) {
    	   if (this == other) return true;
    	   if (! (other instanceof ParametresAppelProc)) return false;
    	   ParametresAppelProc that = (ParametresAppelProc) other;
    	   if (!(this.nomProc.equals(that.nomProc))) return false;
    	   if (this.listParam == null || that.listParam == null) return 
    	   (this.listParam == null && that.listParam == null);
    	   return this.listParam.equals(that.listParam);
       }
     
    }

  12. #12
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    y a plein d'erreurs:

    d'abord, je ne sais pas si c'est voulu, mais ta clé tu lui met des valeur qui n'ont rien à voir avec la fonction (tu lui met id_edge et datestring alors qu'on cherche val et mot)
    ensuite, une list est une mauvais clé pour un Map, la Map exige que la clé soit immutable. Bon on peux garder une liste, mais faut pas la changer après l'avir mise en clé alors.
    enfin, a chaque appel, tu rajoute des valeur dans la même liste, alors que normalement tu devrais avoir une nouvelle liste à chaque fois. En effet, actuellement tu fait cecil
    List = [id_edge,datestring], calcul, ajout dans la map
    ensuite deuxième appel
    List = [id_edge,datestring,id_edge,datestring], existe pas dans la map, recalcul, ajout
    ensuite troisième appel
    List = [id_edge,datestring,id_edge,datestring,id_edge,datestring], existe pas dans la map, recalcul, ajout
    etc etc


    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
        private static  LRUMap Map = new LRUMap() ;
     
     
    public static double loadSelectedval(Connection conn, int val, String mot) throws SQLException, NotFoundException {
     
                List list = new ArrayList<Object>();      
                list.add(val);
                list.add(mot);
                list = Collections.unmodifiableList(list); // pour éviter les emmerdes
                if (!Map.contains(list)){
                    .... calcul de reslutat, de type double
                    map.put(list,resultat); // et stockage
                }
                return (Double)map.get(list);
           }
    Mercii bcp cela marche super bien..
    Je l'ai utilisé pour des fonctions comme cité dans les anciens post et ca marche très bien, plus spécifiquement pour avoir des dataset afin de tracer des courbes ..
    Seulement, quand j'ai voulu l'utiliser pour des tableaux (que je remplie de la manière suivante : j'ai une liste d'éléments, je calcule les valeurs correspondant à chaque élément, je met ces valeurs dans un vecteur, je l'insère dans la table puis je passe au prochain élément, etc, etc..)..
    Dans ce cas, je n'ai pas pu où insérer la vérification de la Map pour ne pas refaire le meme calcul comme j'ai pu le faire avec le dataset du graphe.
    Qu'est ce que je devrais faire pour les tableaux ?!

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    donne ton code qui pose problème, on ne peux pas le deviner

  14. #14
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    donne ton code qui pose problème, on ne peux pas le deviner
    voici mon 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    public void setLoadRateTable (Connection conn, String masg_source, String masg_sink, String datebegin, String dateend, String hour1, String hour2) throws ParseException, SQLException, NotFoundException{
                      List listcol = new ArrayList();
     
                DateFormat formatter;
     
                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");
                SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
                Date date3 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date3 = formatter.parse(datebegin);
                Calendar cal3 = Calendar.getInstance();
                cal3.setTime(date3);
                Date date4 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date4 = formatter.parse(dateend);
                Calendar cal4 = Calendar.getInstance();
                cal4.setTime(date4);
     
                listcol.add("Edge Name");
     
                EdgeDao e_dao = new EdgeDao();
     
                        while ((cal3.compareTo(cal4)) != 0) {
                            listcol.add( sdf.format(cal3.getTime()) );
                            cal3.add(Calendar.DATE, 1);
                        }
     
                listcol.add( sdf.format(cal3.getTime()) );
     
     
                Iterator colit = listcol.listIterator();
     
                jTable1.setAutoCreateColumnsFromModel(false);
     
                while(colit.hasNext()){
                    String coltitle = (String) colit.next();
                    insertColumn(jTable1, coltitle, null, jTable1.getColumnCount());
                }
           // liste des dates de jours
                List listDate = new ArrayList();
                for (int i = 1; i< listcol.size();i++)
                    listDate.add(listcol.get(i));
          // liste des heures
                Date date;
                formatter = new SimpleDateFormat("HH:mm:ss");
                date = formatter.parse(hour1);
                Calendar cal1 = Calendar.getInstance();
                cal1.setTime(date);
                Date date2;
                date2 = (Date) formatter.parse(hour2);
                Calendar cal2 = Calendar.getInstance();
                cal2.setTime(date2);
                List listHour = new ArrayList();
     
                int heure1 = Integer.parseInt(hour1.split(":")[0]);
                 int heure2 = Integer.parseInt(hour2.split(":")[0]);
                 int nombre_heure = heure2 - heure1 ;
                 if (nombre_heure < 0 ){
                     nombre_heure = nombre_heure + 24;
                 }
                 for (int i = 0 ; i<= nombre_heure; i++){
                    listHour.add( sdf2.format(cal1.getTime()));
                    cal1.add(Calendar.HOUR, 1);
                  }
                 cal3.add(Calendar.DATE, 1);
                 if (heure1 > heure2){
                     listDate.add(sdf.format(cal3.getTime()));
                    }
                int   SizelistDate = listcol.size()-1;
     
                List edgeList = e_dao.loadAllEdgeWithSourceMasgNameAndSinkMasgName(conn, masg_source, masg_sink);
                ListIterator<Edge> itedge= edgeList.listIterator();
                while (itedge.hasNext()){
                 Vector v = new Vector();
                    Edge e = itedge.next();
                    v.add(e.getEdge_Name());
     
                    String coltitle ;
                   for (int i =0; i< SizelistDate ; i++){
                       double TrafficBH = 0 ;
                       for (int j=0; j< listHour.size() ; j++){
                            if ( (Integer.parseInt(listHour.get(j).toString().split(":")[0])) >= heure1 ){
                           coltitle = listDate.get(i) + " " + listHour.get(j);
                           } else {
                           coltitle = listDate.get(i+1) + " " + listHour.get(j);
                            }
                            TrafficBH = TrafficBH + LoadRate.TrafficEdge(conn, e.getID_Edge(), coltitle);
     
                            }
                           v.add((double) ((int) ((TrafficBH/listHour.size())*100)) /100 ) ;
     
            }
            addrowtotable(jTable1, v);
        }
        }
    Merci ..

  15. #15
    Membre confirmé
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 44
    Par défaut
    On peut généraliser ce principe que l'on appelle la mémoisation en programmation fonctionnelle (malheureusement Java ne gère pas la mémoisation), mais il est possible de généraliser cette optimisation en créant une méthode mémoize qui appelle la méthode (normale non mémoisée).

    Il suffit donc que la méthode mémoisée reçoive un paramètre sous la forme d'un objet dérivé de la classe Object.

    Si cet objet est trouvé dans une simple Hashtable (déclarée statique généralement), la méthode retourne la valeur associée hashtable.get(objet).

    Sinon, le calcul est réalisée et son résultat est stocké dans la Hashtable avant d'être retourné.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    private static Hashtable m = new Hashtable();
     
    public Object memoize(Object param){
       Object res = m.get(param);
       if(res==null){
          // calcul de res ici...
          res = calculer_res(param);
          m.put(param,res);
       }
       return res;
    }
    Voilà... Un généralisation toute simple...

    Attention, pour être correcte, il est nécessaire que la méthode retourne toujours le même résultat lorsqu'elle reçoit le même paramètre. Il doit s'agir d'une fonction pure.

    Puis pour la gestion de la mémoire, il faut veiller à ne pas utiliser ce genre d'optimisation lorsqu'il y a une infinité de paramètres possibles. On peut aussi ajouté un compteur qui vide la Hashtable au bout d'un certain nombre de calculs ou lorsque la mémoire est remplie.

  16. #16
    Membre chevronné Avatar de NeptuS
    Profil pro
    Inscrit en
    Août 2005
    Messages
    392
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 392
    Par défaut
    Perso, je ne suis pas certain d'avoir bien compris :
    - Quel est ton calcul (où il commence, où il s'arrête et quels sont les paramètres d'entrée). Pour ça, 1 ou 2 commentaires auraient été bienvenus.
    - Dans quelle condition tu as les mêmes valeurs de paramètres d'entrée
    - et enfin, n'ayant pas une vue bien claire de ton code, je vais peut-être dire une bêtise : si tu as des appels à une DB comme tes précédents post semblaient le laisser entendre, oriente-toi vers le réglage du cache de ton SGBD. C'est prévu pour et très efficace. Cela évitera notamment, comme il en a été fait mention plus haut, de te retrouver avec une Map trop imposante à force d'y enregistrer des résultats.

  17. #17
    Membre confirmé
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2011
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 44
    Par défaut
    Je suis d'accord avec NeptuS.

    Dans le cadre d'une base de données, en général, le SGDB gère déjà lui-même des mémoires caches qui lui permettent de renvoyer les derniers résultats plus rapidement.

    Cependant, je crois comprendre que le but de ta question est plutôt de savoir comment on peut éviter d'interroger plusieurs fois la base de données avec la même requête.

    Peut-être faudrait-il revoir ton programme en amont pour voir s'il n'est pas possible d'éviter de répéter des requêtes identiques. Dans tous les cas, c'est ce qu'il y a de mieux à faire.

    Ensuite, si ce n'est pas possible, on peut envisager une mémoisation. En tenant compte du fait qu'elle peut vite devenir volumineuse et remplir inutilement la mémoire si la répétition des mêmes requêtes n'est pas suffisant (il ne faut par trop de résultats différents pour utiliser cette optimisation).

  18. #18
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    je rajoute que pour récupérer des données d'une DB en les mappant vers des objets et en gérant le cache.... il y a hibernate :-)

  19. #19
    Membre confirmé
    Inscrit en
    Février 2011
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 90
    Par défaut
    Citation Envoyé par l.bruninx Voir le message
    On peut généraliser ce principe que l'on appelle la mémoisation en programmation fonctionnelle (malheureusement Java ne gère pas la mémoisation), mais il est possible de généraliser cette optimisation en créant une méthode mémoize qui appelle la méthode (normale non mémoisée).

    Il suffit donc que la méthode mémoisée reçoive un paramètre sous la forme d'un objet dérivé de la classe Object.

    Si cet objet est trouvé dans une simple Hashtable (déclarée statique généralement), la méthode retourne la valeur associée hashtable.get(objet).

    Sinon, le calcul est réalisée et son résultat est stocké dans la Hashtable avant d'être retourné.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    private static Hashtable m = new Hashtable();
     
    public Object memoize(Object param){
       Object res = m.get(param);
       if(res==null){
          // calcul de res ici...
          res = calculer_res(param);
          m.put(param,res);
       }
       return res;
    }
    Voilà... Un généralisation toute simple...

    Attention, pour être correcte, il est nécessaire que la méthode retourne toujours le même résultat lorsqu'elle reçoit le même paramètre. Il doit s'agir d'une fonction pure.

    Puis pour la gestion de la mémoire, il faut veiller à ne pas utiliser ce genre d'optimisation lorsqu'il y a une infinité de paramètres possibles. On peut aussi ajouté un compteur qui vide la Hashtable au bout d'un certain nombre de calculs ou lorsque la mémoire est remplie.
    tchize m'a conseillé d'utiliser LRUMap au lieu de hashmap et cela marche très bien. j'ai bien saisi ta remarque et j'ai bien saisi la méthode.

    Citation Envoyé par NeptuS Voir le message
    Perso, je ne suis pas certain d'avoir bien compris :
    - Quel est ton calcul (où il commence, où il s'arrête et quels sont les paramètres d'entrée). Pour ça, 1 ou 2 commentaires auraient été bienvenus.
    - Dans quelle condition tu as les mêmes valeurs de paramètres d'entrée
    - et enfin, n'ayant pas une vue bien claire de ton code, je vais peut-être dire une bêtise : si tu as des appels à une DB comme tes précédents post semblaient le laisser entendre, oriente-toi vers le réglage du cache de ton SGBD. C'est prévu pour et très efficace. Cela évitera notamment, comme il en a été fait mention plus haut, de te retrouver avec une Map trop imposante à force d'y enregistrer des résultats.
    je vais essayer de répondre à tes questions d'une manière très claire :
    - j'ai déjà mis mon code qui contient la méthode qui va exécuter les requetes. cette méthode fait appel à la meme requete plusieurs fois. la méthode s'appelle TrafficEdge et elle a 2 paramètres : un id et un string.
    - je pense que l'utilisation du cache de mon SGBD aurait été suffisant si et seulement si je vais extraire les memes valeurs de la base de données. mais ce n'est pas le cas pour moi, ce qui signifie que j'ai du me retourner vers LRUmap pour que le résultat se conserve en java.

    Citation Envoyé par l.bruninx Voir le message
    Je suis d'accord avec NeptuS.

    Dans le cadre d'une base de données, en général, le SGDB gère déjà lui-même des mémoires caches qui lui permettent de renvoyer les derniers résultats plus rapidement.

    Cependant, je crois comprendre que le but de ta question est plutôt de savoir comment on peut éviter d'interroger plusieurs fois la base de données avec la même requête.

    Peut-être faudrait-il revoir ton programme en amont pour voir s'il n'est pas possible d'éviter de répéter des requêtes identiques. Dans tous les cas, c'est ce qu'il y a de mieux à faire.

    Ensuite, si ce n'est pas possible, on peut envisager une mémoisation. En tenant compte du fait qu'elle peut vite devenir volumineuse et remplir inutilement la mémoire si la répétition des mêmes requêtes n'est pas suffisant (il ne faut par trop de résultats différents pour utiliser cette optimisation).
    l'écrasement de la map est bien possible, d'après ce que j'ai compris des propos de tchize.

    Citation Envoyé par tchize_ Voir le message
    je rajoute que pour récupérer des données d'une DB en les mappant vers des objets et en gérant le cache.... il y a hibernate :-)
    je ne suis pas entrain d'utiliser Hibernate. mais voici mon problème : j'ai utilisé LRUmap pour les dataset (afin d'afficher des graphes) et ca marche très bien.
    Mais pour des Jtable, je n'ai pas su comment le faire.

    voici mon code qui marche (XYDataset avec LRUmap):
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
     
    public static XYDataset getDatasetForStaticBusyHour (Connection conn, List edgeList, String datebegin, String dateend, String hour1, String hour2) throws ParseException, SQLException, NotFoundException{
            List list = new ArrayList<Object>();
                list.add(edgeList);
                list.add(datebegin);
                list.add(dateend);
                list.add(hour1);
                list.add(hour2);
                list = Collections.unmodifiableList(list);
                if (!Map.containsKey(list)){
     
                    TimeSeriesCollection dataset = new TimeSeriesCollection();
                List listcol = new ArrayList();
     
                DateFormat formatter;
     
                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");
                SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
                Date date3 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date3 = formatter.parse(datebegin);
                Calendar cal3 = Calendar.getInstance();
                cal3.setTime(date3);
                Date date4 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date4 = formatter.parse(dateend);
                Calendar cal4 = Calendar.getInstance();
                cal4.setTime(date4);
     
                listcol.add("Edge Name");
     
                EdgeDao e_dao = new EdgeDao();
     
                        while ((cal3.compareTo(cal4)) != 0) {
                            listcol.add( sdf.format(cal3.getTime()) );
                            cal3.add(Calendar.DATE, 1);
                        }
     
                listcol.add( sdf.format(cal3.getTime()) );
     
     
                Iterator colit = listcol.listIterator();
     
     
                while(colit.hasNext()){
                    String coltitle = (String) colit.next();
                }
           // liste des dates de jours
                List listDate = new ArrayList();
                for (int i = 1; i< listcol.size();i++)
                    listDate.add(listcol.get(i));
          // liste des heures
                Date date;
                formatter = new SimpleDateFormat("HH:mm:ss");
                date = formatter.parse(hour1);
                Calendar cal1 = Calendar.getInstance();
                cal1.setTime(date);
                Date date2;
                date2 = (Date) formatter.parse(hour2);
                Calendar cal2 = Calendar.getInstance();
                cal2.setTime(date2);
                List listHour = new ArrayList();
     
                int heure1 = Integer.parseInt(hour1.split(":")[0]);
                 int heure2 = Integer.parseInt(hour2.split(":")[0]);
                 int nombre_heure = heure2 - heure1 ;
                 if (nombre_heure < 0 ){
                     nombre_heure = nombre_heure + 24;
                 }
                 for (int i = 0 ; i<= nombre_heure; i++){
                    listHour.add( sdf2.format(cal1.getTime()));
                    cal1.add(Calendar.HOUR, 1);
                  }
                 cal3.add(Calendar.DATE, 1);
                 if (heure1 > heure2){
                     listDate.add(sdf.format(cal3.getTime()));
                    }
                ListIterator<String> itedge= edgeList.listIterator();
                while (itedge.hasNext()){
                    Edge e = e_dao.getObject(conn, itedge.next());
                     TimeSeries series = new TimeSeries(e.getEdge_Name(), Day.class);
     
     
                    int DayNumber = 0;
                    int MonthNumber = 0;
                    int YearNumber = 0;
                   for (int i =0; i< SizelistDate ; i++){
                       double TrafficBH = 0 ;
                       MonthNumber = Integer.parseInt(((String) listDate.get(i)).split("/")[0]);
                       DayNumber = Integer.parseInt(((String) listDate.get(i)).split("/")[1]);
                       YearNumber = Integer.parseInt(((String) listDate.get(i)).split("/")[2]);
                       String coltitle ;
                        for (int j=0; j< listHour.size() ; j++){
     
                           if ( (Integer.parseInt(listHour.get(j).toString().split(":")[0])) >= heure1 ){
                           coltitle = listDate.get(i) + " " + listHour.get(j);
                           } else {
                           coltitle = listDate.get(i+1) + " " + listHour.get(j);
                            }
    // LoadTrafficEdge(conn, e.getID_Edge(), coltitle) est la méthode qui exécute la requete
                            TrafficBH = TrafficBH + LoadRate.LoadTrafficEdge(conn, e.getID_Edge(), coltitle);
     
                            }
                       series.add(new Day(DayNumber, MonthNumber, YearNumber), (double) ((int) ((TrafficBH/listHour.size())*100)) /100 );
     
     
            }
              dataset.addSeries(series);
     
        }
               Map.put(list, dataset);//return dataset;
        }
               return (XYDataset) Map.get(list);
        }
    et voici mon code qui consiste à remplir une jtable :
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
     
    public void setLoadRateTable (Connection conn, List edgeList, String datebegin, String dateend, String hour1, String hour2) throws ParseException, SQLException, NotFoundException{
                      List listcol = new ArrayList();
     
                DateFormat formatter;
     
                SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");
                SimpleDateFormat sdf3 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
                Date date3 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date3 = formatter.parse(datebegin);
                Calendar cal3 = Calendar.getInstance();
                cal3.setTime(date3);
                Date date4 ;
                formatter = new SimpleDateFormat("MM/dd/yyyy");
                date4 = formatter.parse(dateend);
                Calendar cal4 = Calendar.getInstance();
                cal4.setTime(date4);
     
                listcol.add("Edge Name");
     
                EdgeDao e_dao = new EdgeDao();
     
                        while ((cal3.compareTo(cal4)) != 0) {
                            listcol.add( sdf.format(cal3.getTime()) );
                            cal3.add(Calendar.DATE, 1);
                        }
     
                listcol.add( sdf.format(cal3.getTime()) );
     
     
                Iterator colit = listcol.listIterator();
     
                jTable1.setAutoCreateColumnsFromModel(false);
     
                while(colit.hasNext()){
                    String coltitle = (String) colit.next();
                    insertColumn(jTable1, coltitle, null, jTable1.getColumnCount());
                }
           // liste des dates de jours
                List listDate = new ArrayList();
                for (int i = 1; i< listcol.size();i++)
                    listDate.add(listcol.get(i));
          // liste des heures
                Date date;
                formatter = new SimpleDateFormat("HH:mm:ss");
                date = formatter.parse(hour1);
                Calendar cal1 = Calendar.getInstance();
                cal1.setTime(date);
                Date date2;
                date2 = (Date) formatter.parse(hour2);
                Calendar cal2 = Calendar.getInstance();
                cal2.setTime(date2);
                List listHour = new ArrayList();
     
                int heure1 = Integer.parseInt(hour1.split(":")[0]);
                 int heure2 = Integer.parseInt(hour2.split(":")[0]);
                 int nombre_heure = heure2 - heure1 ;
                 if (nombre_heure < 0 ){
                     nombre_heure = nombre_heure + 24;
                 }
                 for (int i = 0 ; i<= nombre_heure; i++){
                    listHour.add( sdf2.format(cal1.getTime()));
                    cal1.add(Calendar.HOUR, 1);
                  }
                 cal3.add(Calendar.DATE, 1);
                 if (heure1 > heure2){
                     listDate.add(sdf.format(cal3.getTime()));
                    }
                int   SizelistDate = listcol.size()-1;
     
                ListIterator<String> itedge= edgeList.listIterator();
                while (itedge.hasNext()){
                 Vector v = new Vector();
                    Edge e = e_dao.getObject(conn, itedge.next());;
                    v.add(e.getEdge_Name());
     
     
     
                   for (int i =0; i< SizelistDate ; i++){
                       double TrafficBH = 0 ;
                       String coltitle ;
                        for (int j=0; j< listHour.size() ; j++){
     
                            if ( (Integer.parseInt(listHour.get(j).toString().split(":")[0])) >= heure1 ){
                           coltitle = listDate.get(i) + " " + listHour.get(j);
                           } else {
                           coltitle = listDate.get(i+1) + " " + listHour.get(j);
                            }
    // TrafficEdge(conn, e.getID_Edge(), coltitle) est la méthode qui exécute la requete
                            TrafficBH = TrafficBH + LoadRate.TrafficEdge(conn, e.getID_Edge(), coltitle);
     
                            }
                           v.add((double) ((int) ((TrafficBH/listHour.size())*100)) /100 ) ;
     
            }
            addrowtotable(jTable1, v);
        }
        }
    Il est à noter que le remplissage de JTable et de Dataset ne se fait pas de la meme facon, dans le sens où le remplissage de Dataset se fait valeur par valeur et le remplissage de JTable se fait ligne par ligne.

  20. #20
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Garder un cache de composants graphique n'est pas vraiment une bonne idée

Discussions similaires

  1. [VBA-Excel]Avoir une boite de dialogue avec les arguments des fonctions ?
    Par EvaristeGaloisBis dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 29/05/2007, 10h37
  2. Mesurer le temps de calcul des fonctions
    Par dzada dans le forum Caml
    Réponses: 2
    Dernier message: 12/03/2007, 20h54
  3. pointeurs sur les arguments des fonctions?
    Par brunoP dans le forum C
    Réponses: 3
    Dernier message: 14/05/2006, 19h11
  4. Comment afficher dans une combobox les driver des imprimante
    Par lassad dans le forum Composants VCL
    Réponses: 3
    Dernier message: 18/10/2005, 09h56

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