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

Collection et Stream Java Discussion :

methode trop gourmande


Sujet :

Collection et Stream Java

  1. #1
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut methode trop gourmande
    Bonjour à tous, j'utilise une méthode en java qui permet de m'extraire du code html qui pour un planning.

    Si mon planning n'a pas beaucoup de ligne tout va bien mais à partir d'une dizaine de ligne j'ai un message disant que mon agent utilise beaucoup de mémoire.

    Je pense que cela vient de la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for (int i = 0; i < persons.size(); i++) {
    				PlanningPerson pP = (PlanningPerson) persons.elementAt(i);
    				sb.append(pP.lineHTML());
     
    			}
    persons est un vecteur qui contient des objets PlanningPerson
    Je parcours ce vecteur et charge à chaque fois ses objets, je pense que c'est cela qui prend beaucoup de mémoire.
    Il faudrait que je puisse libérer pP à chaque fois.

    Comment je pourrais faire svp ?

    Merci.

  2. #2
    Membre Expert
    Avatar de CheryBen
    Inscrit en
    Mai 2005
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 599
    Par défaut
    Bonjour, je te conseille de jeter un oeil à cette page de la FAQ : Pourquoi ne faut-il pas employer la classe Vector ?

    Ormis cela, il est difficile de voir d'où vient le problème sans connaitre l'exception ni avoir plus de code.

  3. #3
    Membre averti
    Femme Profil pro
    Inscrit en
    Avril 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : Tunisie

    Informations forums :
    Inscription : Avril 2008
    Messages : 33
    Par défaut
    Bonjour ,

    Je vais te donner une proposition , mais franchement je ne suis pas sur que c'est ça la raison ,

    Au lieu de ça : for (int i = 0; i < persons.size(); i++) {

    Essaye de faire
    for(iterator it = persons.iterator ; it.hasNext() ; ) {


    PlanningPerson pP = (PlanningPerson) it.next();;
    sb.append(pP.lineHTML());

    }

  4. #4
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    Merci pour vos réponses.

    J'ai remplacé les Vector par des ArrayList, mais je n'ai pas trop gagné en perf, je reste à 13% (Agent memory usage (13) percentage of total)

    J'utilise également l'iterator.

    En fait je n'ai pas d'exception, c'est juste un avertissement du serveur ou est exécuté l'agent java.

    Je peux peut être vous envoyer les deux classes si vous le voulez.

    Merci.

  5. #5
    Membre averti
    Femme Profil pro
    Inscrit en
    Avril 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : Tunisie

    Informations forums :
    Inscription : Avril 2008
    Messages : 33
    Par défaut
    Rebonjour ,

    Oui tu peux envoyer les classes si tu veux , pour qu'on puisse savoir la cause du ce problème.

  6. #6
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    Commence par éviter les déclarations de références dans une boucle.

  7. #7
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Citation Envoyé par Marco46 Voir le message
    Commence par éviter les déclarations de références dans une boucle.
    Et pourquoi donc ?

  8. #8
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Citation Envoyé par seroa Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i = 0; i < persons.size(); i++) {
    				PlanningPerson pP = (PlanningPerson) persons.elementAt(i);
    				sb.append(pP.lineHTML());
    							}
    Il faudrait que je puisse libérer pP à chaque fois.
    Comment je pourrais faire svp ?
    La variable pP est modifiée à chaque tour de boucle, tu n'as pas à libérer quoique ce soit, ce n'est qu'une référence vers un des objets contenus dans le vecteur persons. Ce qui peut être gros, c'est le code HTML renvoyée par lineHTML() et/ou le contenu du StringBuilder résultat de la concaténation des codes HTML

  9. #9
    Expert confirmé
    Avatar de Marco46
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2005
    Messages
    4 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2005
    Messages : 4 419
    Par défaut
    Citation Envoyé par herve91 Voir le message
    La variable pP est modifiée à chaque tour de boucle, tu n'as pas à libérer quoique ce soit, ce n'est qu'une référence vers un des objets contenus dans le vecteur persons. Ce qui peut être gros, c'est le code HTML renvoyée par lineHTML() et/ou le contenu du StringBuilder résultat de la concaténation des codes HTML
    Effectivement j'ai dit une connerie. Autant pour moi !

  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
    je gagerais, à vue de nez, que ton problème de perfs (qu'on a pas identifié d'ailleurs, tu parle de 13% , mais 13% de quoi??!), si il existe, viens de PlanningPerson.lineHTML(). La boucle en elle-même n'a aucun soucis (sauf si chaque ligne HTML fait 10M, mais j'en doute)

  11. #11
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    Bonjour à tous et merci pour vos réponses.

    J'ai toujours ce problème de mémoire. En fait c'est la console du serveur domino qui m'envoie ce message lorsque mon agent java est lancé.

    Je pense aussi que le problème vient de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sb.append(pP.lineHTML());
    , c'est assez long ce que renvoi pP.lineHTML().

    Mais pourquoi il affiche un message qu'à partir d'un certain nombre de ligne ?

    J'ai le message seulement après une modification, lorsque je relance le planning et que celui-ci n'a pas été modifié, il n'affiche pas le message, comme s'il l'avait gardé en cache.

    Merci.

  12. #12
    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
    on a pas le code de ton lineHTML, donc impossible de te dire pourquoi il prend de l'espace en mémoire!

  13. #13
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    J'ai ajouté

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long heapSize = Runtime.getRuntime().totalMemory();
    dans ma boucle, mais le chiffre ne change jamais.

    lineHTML renvoi le texte suivant à peu pres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <td width="200">Nom Prenom</td><td title="Weekend" class="weekend" colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td colspan="2"></td><td title="Leave: All day" onclick="window.open('/Base.nsf/Leave/60F1C034B3A3EBF6C125771C003AFAE4?OpenDocument&page=P')" class="leave" colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td title="Weekend" class="weekend" colspan="2"></td><td colspan="2"></td><td colspan="2"></td><td class="last"></td></tr><tr onmouseover="this.className='grey'"; onmouseout="this.className='white'"; ><td class="title" width="3"></td>
    Merci.

  14. #14
    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
    c'est pas le texte qui importe mais le code de la méthode.... Et combien de append tu fait dans ton buffer....

  15. #15
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    voila le code de la méthode :

    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
    /**
             * <b> return HTML code for 1 line of planning </b>
             * @return String : html code
             */
    	public String lineHTML() {
    		StringBuffer result = new StringBuffer();
     
    		//Name
    		result.append("<tr onmouseover=\"this.className='grey'\"; onmouseout=\"this.className='white'\"; ><td class=\"title\" width=\"3\"></td><td width=\"200\">");
    		result.append(this.name);
    		result.append("</td>");
     
    		//Week end Verification, leave verification
    		// Else : white line
    		GregorianCalendar gc = new GregorianCalendar();
    		try {
     
    			//For every days :
    			for (int i = 1; i <= getNbDaysOfMonth(); i++) {
    				// Calendar initialization
    				gc.set(getYear(), getMonth(), i);
     
    				// Holidays :
    				ArrayList holidays = new ArrayList();
    				holidays = getHoliday();
    				Integer dInteger = new Integer(i);
    				if (holidays.contains(dInteger)) {
    					result.append(insertHoliday());
    				} else {
    					// If week end : 
    					if (gc.get(Calendar.DAY_OF_WEEK) == 1 || gc.get(Calendar.DAY_OF_WEEK) == 7){
    						//if(gc.get(Calendar.DAY_OF_WEEK) == 7) {
    							result.append(insertWeekEnd());
    						//}
    					} else {
    						// Current day recovery
    						String d = new String(String.valueOf(i));
    						// If current day in list of leaves days :
    						if (days.contains(d)) {
    							// index recovery 
    							int index = days.indexOf(d);
    							// type recovery
    							String type = new String((String) types.get(index));
    							String docId = new String((String) docIds.get(index));
    							// type CSS recovery according to the type
    							String css = CSS_LEAVE;
    							if(TYPE_LEAVE_UNPAID.equalsIgnoreCase(type)) {
    								css = CSS_UNPAID_LEAVE;
    							}
    							if (TYPE_LEAVE_RECUPERATION.equalsIgnoreCase(type)) {
    								css = CSS_RECUPERATION;
    							}
    							if (TYPE_LEAVE_REQUEST.equalsIgnoreCase(type)) {
    								css = CSS_REQUEST;
    							}
    							if (TYPE_LEAVE_SPECIAL.equalsIgnoreCase(type)) {
    								css = CSS_SPECIAL;
    							}
    							if (TYPE_LEAVE_OTHER.equalsIgnoreCase(type)) {
    								css = CSS_OTHER;
    							}
    							// duration recovery
    							// if half day : 1 cell else 2 cells in table
    							String duration = new String((String) durations.get(index));
     
    							result.append(insertLeave(css, duration, docId, type));
     
     
    						} else {
    							// write line
    							result.append("<td colspan=\"2\"></td>");
    						}
    					}
    				}
    			}
    		}finally {
    			gc = null;
    		}
    		result.append(emptyCol());
    		result.append("</tr>");
     
    		return result.toString();
     
    	}

  16. #16
    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
    elle ne fait rien de particulier. Alors soit tu a énormément de personnes dans ton vecteur -> ton stringbuffer deviens énorme, soit tu conserver des données en cache ailleur et, au fur et à mesure de l'utilisation de ton application, la consommation mémoire augmente. Dans ce dernier cas, utiliser un profiler pour détecter les points chaud en termes de mémoire de ton application....

  17. #17
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    Le problème doit venir de mon StringBuffer qui devient de plus en plus gros quand le nombre de personne augmente.

    J'aurais bien utilisé un StringBuilder qui apparemment est plus performant mais la JVM de domino 7 est en 1.4 et il reconnait pas la classe StringBuilder.

  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
    String Buffer ou String builder n'y change rien, quelle taille fait le texte que tu met dedans? Avec 1M de mémoire, on peut déjà créer un StringBuilder qui est formé de 10.000 personnes, si chaque personne occupe une centaine de caractères.....

    A moins de mettre des millions de gens dedans, je suspecte plus un leak ailleurs.

  19. #19
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    135
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 135
    Par défaut
    Mon StringBuffer est composé en moyenne de 20 x 2000 caractères environ.

    En reduisant mon StringBuffer à 20 x 1000 caractère environ, je n'ai plus le message.

    Pour cela, j'ai supprimer ma ligne insertLeave(css, duration, docId, type)

    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
    public String insertLeave(final String css, final String duration, final String docId, final String type) {
    		StringBuffer result = new StringBuffer();
    		try {
    			if("PM".equalsIgnoreCase(duration)) {
    				result.append("<td></td><td");
    			} else {
    				result.append("<td");
    			}
     
    			result.append(" title=\"")
    			      .append(type)
    			      .append(": ")
    			      .append(duration)
    			      .append("\" onclick=\"window.open('/")
    			      .append(getDbName())
    			      .append("/Leaves/")
    			      .append(docId)
    			      .append("?OpenDocument&page=P')\" class=\"")
    			      .append(css);
     
    			if ("All day".equalsIgnoreCase(duration)) {
    				result.append("\" colspan=\"2\"></td>");
    			} else {
    				if ("AM".equalsIgnoreCase(duration)){
    					result.append("\"></td><td></td>");
    				} else {
    					result.append("\"></td>");
    				}
    			}
     
    			return result.toString();
    		} finally {
    			result = null;
    		}
    	}
    Mais je ne voit rien qui ne va pas dans mon insertLeave.

  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
    Citation Envoyé par seroa Voir le message
    Mon StringBuffer est composé en moyenne de 20 x 2000 caractères environ.

    Mais je ne voit rien qui ne va pas dans mon insertLeave.
    Soit 40k d'occupation mémoire (80k en pic lors des resize du buffer), rien d'inquiétant. On ne sait toujours pas de quelle quantité de mémoire on parle non plus, quand tu dit que tu consomme trop. Tu nous dit 13% mais on sait toujours pas 13% de quoi.

    enfin, rien ne dit que c'est ce buffer en cause, juste le déclencheur (celui qui fait passer ton "agent" hors limites), mais une allocation de quelques octet peut aussi être déclencheur. Si j'ai une limite de 200M et que j'alloue 199.9M quelque part, ce sera le petit bout de code qui mange 100k qui sera visé par l'erreur de outofmemory.

    Donc

    1) mesure de quelle quantité de mémoire on parle là (on en sait toujours rien)
    2) un fois ça fait et si relevant, utiliser un profiler pour repérer les point chaud de ton code en mémoire.
    3) une fois les point chaud identifier, repérer qui à alloué ces donnée, pourquoi et surtout pourquoi elles ne sont pas libérées (donc qui en garde une référence).

Discussions similaires

  1. requete trop gourmande
    Par nicerico dans le forum Requêtes
    Réponses: 3
    Dernier message: 26/03/2009, 15h23
  2. Inserts trop gourmand en mémoire
    Par ledjlale dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 05/11/2008, 22h51
  3. Script trop gourmand en ressources
    Par zevince dans le forum Langage
    Réponses: 4
    Dernier message: 01/06/2007, 05h30
  4. [Tableaux] count trop gourmande ?
    Par Anubis dans le forum Langage
    Réponses: 3
    Dernier message: 12/02/2007, 16h45
  5. Optimiser une table sur SQL server trop gourmande en CPU
    Par molarisapa dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/06/2006, 17h17

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