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

Applets Java Discussion :

Dépassement de mémoire avec un crawler


Sujet :

Applets Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut Dépassement de mémoire avec un crawler
    Bonjour,

    Mon applet n'arrête pas de planter à cause des Java Heapspace memory error. C'est un crawler et à environ 5000 urls il plante. Je pense que ce qui prend de la place c'est les URLs que je stocke sur une pile pour verifier qu'on y es pas déjà passé.

    Y a-t-il un moyen de réduire cette taille ? Base de données ? Ecriture de la liste dans un fichier ? Compression des String pour comparaison ?

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Je ne pense pas non, 5000 URLs, à supposer que les urls soient très longues (genres 3000 charactères), ça occuperait environ 30M, pas de quoi saturer la heap.


    Si tu nous montrait ton code, il doit y avoir une récursion qui occupe beaucoup de mémoire et sature la heap....

  3. #3
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Par ailleurs, un crawler dans une applet...? Et aussi : pourquoi une pile ? En plus tu vérifie l'existence "à la main" ? Mais bon de toutes façons, quelle que soit la mémoire allouée tu vas finir par la saturer, vu que www.* ne tiendra jamais dans quelques gigas... Alors qu'avec une base SQL c'est aussi automatique et "jamais" saturé...
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Tu as raison, je ne comprend pas non plus. Voici mon code (mais il est un peu long)

    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
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    package netsur2;
    import java.net.URL;
    import java.util.*;
    import java.util.regex.*;
     
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.ResponseHandler;
    import org.apache.http.impl.client.BasicResponseHandler;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.CoreProtocolPNames;
     
    // http://pageperso.lif.univ-mrs.fr/~andreea.dragut/enseignementWebMining/r/tp1.html
     
    public class SimpleCrawler {
     
        public static SimpleCrawler factory(String urlFourni) throws Throwable {
     
        // on se prend la liste des URLs a parcourir
    	Queue<CrawlerUrl> urlQueue = new LinkedList<CrawlerUrl>();
    	// l'url de demarrage du crawler
    	String url = urlFourni;
    	// on le met dans la liste
    	CrawlerUrl cr=new CrawlerUrl(url, 0);
    	urlQueue.add(cr);
    	Applet_VeilleConcurentielle.console("Demarrage du crawler sur "+url+"   /   Start of crawler on "+url);
    	SimpleCrawler crawler=new SimpleCrawler(urlQueue,100,3,100L);
     
    	String[] ext=".css,.js,.bmp,.gif,.jpeg,.jpg,.png,.tif,.tiff,.mid,.mp2,.mp3,.mp4,.wav,.avi,.mov,.mpeg,.ram,.m4v,.pdf,.rm,.smil,.wmv,.swf,.wma,.zip,.rar,.gz".toLowerCase().split(",");
    	crawler.extensions=new ArrayList<String>(Arrays.asList(ext));
     
    	crawler.domaineSite=cr.getURL().getHost();
    	return crawler;
        }
     
     
        private static final String USER_AGENT = "User-agent:";
        private static final String DISALLOW   = "Disallow:";
     
        public long maxNumberUrls;
        public long delayBetweenUrls;
        public int maxDepth;
        public String userAgent="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
     
        public String regexTitre;
        public String regexPrix;
        public int numMasqueTitre;
        public int numMasquePrix;
     
        public ArrayList<String> extensions=new ArrayList<String>();
     
        private Map<String, CrawlerUrl> visitedUrls             = null;
        private Map<String, Collection<String>> sitePermissions = null;
     
        private String domaineSite;
     
        public Queue<CrawlerUrl> urlQueue                      = null;
     
        public SimpleCrawler(Queue<CrawlerUrl> urlQueue, int maxNumberUrls,
    			 int maxDepth, long delayBetweenUrls)
                throws Exception {
    	//System.out.println("SimpleCrawler::SimpleCrawler()");
     
            this.urlQueue         = urlQueue;
            this.maxNumberUrls    = maxNumberUrls;
            this.delayBetweenUrls = delayBetweenUrls;
            this.maxDepth         = maxDepth;
            this.visitedUrls      = new HashMap<String, CrawlerUrl>();
            this.sitePermissions  = new HashMap<String, Collection<String>>();
        }
     
        public void crawl() throws Exception { // methode principale 
            while (continueCrawling()) { // tant qu'on a des URLs a parcourir
                // et qu'on remplit les conditions (profondeur, n max, etc.) 
                CrawlerUrl url = getNextUrl(); // au suivant 
                if (url != null) {
                    printCrawlInfo(); // affichage+sauvgrd dans crawlStatistics
    		getContent(url);  // recuperation du contenu depuis le web 
    		saveContent(url); // sauvgrd texte dans download_<docId>.txt
    		                  // du titre dans title_<docId>.txt, etc. 
    		addUrlsToUrlQueue(url); // liens sortants dans la queue
    		saveLinks(url);   //liens sortants -> outlinkurls_<docId>.txt
    		Thread.sleep(this.delayBetweenUrls); // pour ne pas assommer 
    		                                     // les serveurs 
                }
            }
    	generateOutlinksIds(); // lecture de crawl.txt avec construction de 
                                   // la table de hachage et puis pour chaque 
                                   // outlinkurls_<docId>.txt, ecriture de 
    	                       // outlinks_<docId>.txt qui contient les 
    	                       // docIds atteignables 
        }
     
        private boolean continueCrawling() { // savoir si on peut continuer
    	boolean qContinue = (!urlQueue.isEmpty()) && 
    	    (getNumberOfUrlsVisited() < this.maxNumberUrls);
    	//System.out.println("Deciding whether to continue crawling ... " + String . valueOf(qContinue) + " ..");
            return (qContinue); 
        }
     
        private CrawlerUrl getNextUrl() {  // obtenir l'URL suivant a explorer 
            CrawlerUrl nextUrl = null;
            while ((nextUrl == null) && (!urlQueue.isEmpty())) {
                CrawlerUrl crawlerUrl = this.urlQueue.remove();
                if (doWeHavePermissionToVisit(crawlerUrl)
                        && (!isUrlAlreadyVisited(crawlerUrl))
                        && isDepthAcceptable(crawlerUrl)) {
                    nextUrl = crawlerUrl;
                    //System.out.println("Le prochain url a visiter est "+nextUrl);
                }
            }
            return nextUrl;
        }
     
        // maintenant il y a quelques methodes auxiliaires 
     
        private void printCrawlInfo() throws Exception {
        	int nb=getNumberOfUrlsVisited();
        	if(nb!=0 && nb % 100 ==0)
        	{
        		Applet_VeilleConcurentielle.console("Crawling en cours... "+nb+" URL analysés    /    Crawling in progress... "+nb+" URL visited      --     "+Fc.aujourdhui("dd/MM/yyyy HH:mm:ss"));
        	}
            /* StringBuilder sb = new StringBuilder();
            sb.append("Queue length = ").append(this.urlQueue.size()).append(
                    " visited urls=").append(getNumberOfUrlsVisited()).append(
                    " site permissions=").append(this.sitePermissions.size());
            System.out.println(sb.toString()); */
        }
     
        private int getNumberOfUrlsVisited() {
            return this.visitedUrls.size();
        }
     
        private boolean isDepthAcceptable(CrawlerUrl crawlerUrl) {
            return crawlerUrl.getDepth() <= this.maxDepth;
        }
     
        private boolean isUrlAlreadyVisited(CrawlerUrl crawlerUrl) {
            if ((crawlerUrl.isVisited())
    	    || (this.visitedUrls.containsKey(crawlerUrl.getUrlString()))) {
                return true;
            }
            return false;
        }
     
        public boolean doWeHavePermissionToVisit(CrawlerUrl crawlerUrl) {
            if (crawlerUrl == null) {
                return false;
            }
            if (!crawlerUrl.isCheckedForPermission()) {
                crawlerUrl.setAllowedToVisit(
    		computePermissionForVisiting(crawlerUrl));
            }
            // We need to check
            return crawlerUrl.isAllowedToVisit();
        }
     
     
        private boolean computePermissionForVisiting(CrawlerUrl crawlerUrl) {
            URL url = crawlerUrl.getURL();
            boolean retValue = (url != null);
            if (retValue) {
                String host  = url.getHost();
            if(!host.equals(domaineSite)) return false; //rester dans le domaine
            if(!crawlerUrl.extensionAutoriser(extensions)) return false; //extensions autorisées
    	    String port  = "";
    	    int    portN = url.getPort();
    	    if(portN > -1) {
    		port = ":" + String.valueOf(portN);
    	    }
                Collection<String> disallowedPaths=this.sitePermissions.get(host);
                if (disallowedPaths == null) {
                    disallowedPaths = 
    		    parseRobotsTxtFileToGetDisallowedPaths(host+port);
                }
                // On itere pour tous les chemins interdits (disallowed paths)
                String path = url.getPath();
                if(path!="" && path!="/")
                {
    	            for (String disallowedPath : disallowedPaths) {
    	                if (path.equals(disallowedPath)) {
    	                    retValue = false;
    	                }
    	            }
                }
            }
            return retValue;
        }
     
        private Collection<String> parseRobotsTxtFileToGetDisallowedPaths(
                String host) {
            String robotFilePath = getContent("http://" + host + "/robots.txt");
            Collection<String> disallowedPaths = new ArrayList<String>();
            if (robotFilePath != null) {
                Pattern p = Pattern.compile(USER_AGENT);
                String[] permissionSets = p.split(robotFilePath);
                String permissionString = "";
                for (String permission : permissionSets) {
                    if (permission.trim().startsWith("*")) {
                        permissionString = permission.substring(1);
                    }
                }
                p = Pattern.compile(DISALLOW);
                String[] items = p.split(permissionString);
                for (String s : items) {
                    disallowedPaths.add(s.trim());
                    // System.out.println(s.trim());
                }
            }
            this.sitePermissions.put(host, disallowedPaths);
            return disallowedPaths;
        }
     
        private String getContent(String urlString) {
            return getContent(new CrawlerUrl(urlString, 0));
        }
     
        private String getContent(CrawlerUrl url) { // methode essentielle -- 
            // recuperation du fichier .html depuis le serveur
    	HttpClient httpclient = new DefaultHttpClient();
    	String userAgent = this.userAgent;
    	httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, userAgent);
    	String text = new String();
            try {
                HttpGet httpget = new HttpGet(url.getUrlString()); //construction
    	    //  de l'objet qui fera la connexion
     
                //System.out.println("executing request " + httpget.getURI());
                // construction de l'objet qui gerera le dialogue avec le serveur 
                ResponseHandler<String> responseHandler = 
    		new BasicResponseHandler();
                try {
                text = httpclient.execute(httpget, responseHandler); //et on y va
                } catch(Exception e) {}
    	}
    	catch(Throwable t) {
    	    System.out.println("Echec du chargement de "+url.getUrlString()+" "+ t . toString());
    	    //t . printStackTrace();
    	}
    	finally {
                // Lorsque on n'a plus besoin de l'objet de type HttpClient
                // on ferme la connexion pour eliberer rapidement les resources
                // systeme qu'on avait monopolisees
                httpclient.getConnectionManager().shutdown();
            }
            markUrlAsVisited(url); // on marque l'URL
    	url . setRawContent(text); // on donne le texte HTML brut au parseur
    	// appele dans la classe CrawlerUrl -- qui en extrait le texte, 
    	// le titre, les liens sortants, etc. (apres avoir parse le texte 
    	// HTML ainsi fourni)
            return text;
     
        }
     
        private void markUrlAsVisited(CrawlerUrl url) {
            this.visitedUrls.put(url.getUrlString(), url);
            url.setIsVisited();
        }
     
        private void saveContent(CrawlerUrl url)  throws Exception {
    		String content = url . getHTML();
    		//String title   = url . getTitle();
    		String urlPage = url . getUrlString();
     
     
    		String titre=Fc.trouverTxt(regexTitre, content,numMasqueTitre);
    		String prix=Fc.trouverTxt(regexPrix, content,numMasquePrix);
     
     
    		if(titre!=null && titre!="" && prix!=null && prix!="")
    		{
    			Produit pr=new Produit();
    			pr.setName(titre);
    			pr.setPrix(prix);
    			pr.lien=urlPage;
     
    			if(Applet_VeilleConcurentielle.pileProduitCourante!=null) Applet_VeilleConcurentielle.pileProduitCourante.aj(pr);
    		}
     
     
    		url.raz();
        }
     
        private void saveLinks(CrawlerUrl url) throws Exception {
        	//sauvegarder liens
        }
     
        private void addUrlsToUrlQueue(CrawlerUrl url) {
    	Collection<String> urlStrings = url . getLinks();
            int depth = url.getDepth() + 1;
            for (String urlString : urlStrings) {
                if (!this.visitedUrls.containsKey(urlString)) {
                     this.urlQueue.add(new CrawlerUrl(urlString, depth));
                }
            }
        }
     
        private void generateOutlinksIds() throws Exception{
        	//la méthode semble innutile
        }
    }
    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
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    package netsur2;
    import java.net.MalformedURLException;
    import java.net.URL;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
     
    import java.util.*;
     
    public class CrawlerUrl {
        // donnees et methodes pour l'URL elle-meme (en tant qu'"addresse web")
     
        private int depth = 0;
        private String urlString = null;
        private URL url = null;
        private boolean isAllowedToVisit;
        private boolean isCheckedForPermission = false;
        private boolean isVisited = false;
     
        public CrawlerUrl(String urlString, int depth) {
            this.depth = depth;
            this.urlString = urlString;
            computeURL();
        }
     
        private void computeURL() {
        	int isDiese=urlString.indexOf("#");
        	if (isDiese>-1) urlString=urlString.substring(0, isDiese);
            try {
                url = new URL(urlString);
            } catch (MalformedURLException e) {
    	    // petit probleme
            }
        }
     
        public URL getURL() {
            return this.url;
        }
     
        public int getDepth() {
            return this.depth;
        }
     
        public boolean isAllowedToVisit() {
            return isAllowedToVisit;
        }
     
        public void setAllowedToVisit(boolean isAllowedToVisit) {
            this.isAllowedToVisit = isAllowedToVisit;
            this.isCheckedForPermission = true;
        }
     
        public boolean isCheckedForPermission() {
            return isCheckedForPermission;
        }
     
        public boolean isVisited() {
            return isVisited;
        }
     
        public void setIsVisited() {
            this.isVisited = true;
        }
     
        public String getUrlString() {
            return this.urlString;
        }
     
        @Override
        public String toString() {
            return this.urlString + " [depth=" + depth + " visit="
                    + this.isAllowedToVisit + " check="
                    + this.isCheckedForPermission + "]";
        }
     
        @Override
        public int hashCode() {
            return this.urlString.hashCode();
        }
     
        @Override
        public boolean equals(Object obj) {
            return obj.hashCode() == this.hashCode();
        }
     
        // donnees et methodes concernant le contenu telecharge depuis l'URL
     
        private String       htmlText;
        private Document     htmlJsoupDoc;
        private String       niceText;
        private String       title;
        private List<String> linkList;
     
        public String getHTML() {
    	return(htmlText);
        }
     
        public String getNiceText() {
    	return(niceText);
        }
     
        public String getTitle() {
    	return(title);
        }
     
        public List<String> getLinks() {
    	return(linkList);
        }
     
        public void raz()
        {
        	htmlJsoupDoc=null;
        	htmlText=null;
        	niceText=null;
        	title=null;
        }
     
        public void setRawContent(String htmlText) {
    	String baseURL  = getURL() . toExternalForm();
    	this . htmlText = htmlText;
    	htmlJsoupDoc    = Jsoup . parse(htmlText,baseURL);
    	title           = htmlJsoupDoc . title();
    	//niceText        = htmlJsoupDoc . body() . text();
    	linkList        = new ArrayList<String>();
    	Elements hrefJsoupLinks = htmlJsoupDoc . select("a[href]");
            for (Element link : hrefJsoupLinks) {
    	    String thisLink = link.attr("abs:href");
    	    if(thisLink . startsWith("http://")) {
    		//System.out.println("JSOUP Found: " + thisLink);
    		linkList . add(thisLink);
    	    }
    	}		
        }
     
        public boolean extensionAutoriser(ArrayList<String> refuser)
        {
        	String path=url.getPath().toLowerCase();
        	for(String ext:refuser)
        	{
        		if(path.endsWith(ext)) return false;
        	}
        	return true;
        }
     
    }

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Heu, chaque CrawlerURL contient tout le html et le structure du document téléchargé mais... Tu stocke ce crawlerURL dans une list de visited après usage -> Tu garde au final en mémoire le contenu de tous les documents visité. Ca peux vite grimper. à 50k / document, avec 5000URL, t's à 250M

    Commence par remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        private Map<String, CrawlerUrl> visitedUrls             = null;
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        private Set<String> visitedUrls             = null;
     
        private boolean isUrlAlreadyVisited(CrawlerUrl crawlerUrl) {
            return crawlerUrl.isVisited() || visitedUrls.contains(crawlerUrl.getUrlString());
        }
     
        private void markUrlAsVisited(CrawlerUrl url) {
            this.visitedUrls.add(crawlerUrl.getUrlString());
            url.setIsVisited();
        }
    et tu gagnera déjà beaucoup de place (Surtout, que tu ne récupère pas ce CrawlerURL par la suite, donc tu le stocke pour rien !!)

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Merci, à force de relire le même code j'avais les idées embrouillées.

    J'ai fait la modif mais malheureusement l'applet vient de crasher à 4400 URL...

    Pour info, voici le graph de Java VisualVM

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    tu peux nous reposter ton code modifé, il manque peut être quelque chose

    Profite de visualVM pour regarder quels objets occupent ta mémoire et qui les a instancés

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Deux objets se détachent String et char*. Ca ne dis pas grand chose tout ça.

    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
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    package netsur2;
    import java.net.URL;
    import java.util.*;
    import java.util.regex.*;
     
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.ResponseHandler;
    import org.apache.http.impl.client.BasicResponseHandler;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.CoreProtocolPNames;
     
    // http://pageperso.lif.univ-mrs.fr/~andreea.dragut/enseignementWebMining/r/tp1.html
     
    public class SimpleCrawler {
     
        public static SimpleCrawler factory(String urlFourni) throws Throwable {
     
        // on se prend la liste des URLs a parcourir
    	Queue<CrawlerUrl> urlQueue = new LinkedList<CrawlerUrl>();
    	// l'url de demarrage du crawler
    	String url = urlFourni;
    	// on le met dans la liste
    	CrawlerUrl cr=new CrawlerUrl(url, 0);
    	urlQueue.add(cr);
    	Applet_VeilleConcurentielle.console("Demarrage du crawler sur "+url+"   /   Start of crawler on "+url);
    	SimpleCrawler crawler=new SimpleCrawler(urlQueue,100,3,100L);
     
    	String[] ext=".css,.js,.bmp,.gif,.jpeg,.jpg,.png,.tif,.tiff,.mid,.mp2,.mp3,.mp4,.wav,.avi,.mov,.mpeg,.ram,.m4v,.pdf,.rm,.smil,.wmv,.swf,.wma,.zip,.rar,.gz".toLowerCase().split(",");
    	crawler.extensions=new ArrayList<String>(Arrays.asList(ext));
     
    	crawler.domaineSite=cr.getURL().getHost();
    	return crawler;
        }
     
     
        private static final String USER_AGENT = "User-agent:";
        private static final String DISALLOW   = "Disallow:";
     
        public long maxNumberUrls;
        public long delayBetweenUrls;
        public int maxDepth;
        public String userAgent="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
     
        public String regexTitre;
        public String regexPrix;
        public int numMasqueTitre;
        public int numMasquePrix;
     
        public ArrayList<String> extensions=new ArrayList<String>();
     
        private Set<String> visitedUrls             = null;
        private Map<String, Collection<String>> sitePermissions = null;
     
        private String domaineSite;
     
        public Queue<CrawlerUrl> urlQueue                      = null;
     
        public SimpleCrawler(Queue<CrawlerUrl> urlQueue, int maxNumberUrls,
    			 int maxDepth, long delayBetweenUrls)
                throws Exception {
    	//System.out.println("SimpleCrawler::SimpleCrawler()");
     
            this.urlQueue         = urlQueue;
            this.maxNumberUrls    = maxNumberUrls;
            this.delayBetweenUrls = delayBetweenUrls;
            this.maxDepth         = maxDepth;
            this.visitedUrls      = new HashSet<String>();
            this.sitePermissions  = new HashMap<String, Collection<String>>();
        }
     
        public void crawl() throws Exception { // methode principale 
            while (continueCrawling()) { // tant qu'on a des URLs a parcourir
                // et qu'on remplit les conditions (profondeur, n max, etc.) 
                CrawlerUrl url = getNextUrl(); // au suivant 
                if (url != null) {
                    printCrawlInfo(); // affichage+sauvgrd dans crawlStatistics
    		getContent(url);  // recuperation du contenu depuis le web 
    		saveContent(url); // sauvgrd texte dans download_<docId>.txt
    		                  // du titre dans title_<docId>.txt, etc. 
    		addUrlsToUrlQueue(url); // liens sortants dans la queue
    		saveLinks(url);   //liens sortants -> outlinkurls_<docId>.txt
    		Thread.sleep(this.delayBetweenUrls); // pour ne pas assommer 
    		                                     // les serveurs 
                }
            }
    	generateOutlinksIds(); // lecture de crawl.txt avec construction de 
                                   // la table de hachage et puis pour chaque 
                                   // outlinkurls_<docId>.txt, ecriture de 
    	                       // outlinks_<docId>.txt qui contient les 
    	                       // docIds atteignables 
        }
     
        private boolean continueCrawling() { // savoir si on peut continuer
    	boolean qContinue = (!urlQueue.isEmpty()) && 
    	    (getNumberOfUrlsVisited() < this.maxNumberUrls);
    	//System.out.println("Deciding whether to continue crawling ... " + String . valueOf(qContinue) + " ..");
            return (qContinue); 
        }
     
        private CrawlerUrl getNextUrl() {  // obtenir l'URL suivant a explorer 
            CrawlerUrl nextUrl = null;
            while ((nextUrl == null) && (!urlQueue.isEmpty())) {
                CrawlerUrl crawlerUrl = this.urlQueue.remove();
                if (doWeHavePermissionToVisit(crawlerUrl)
                        && (!isUrlAlreadyVisited(crawlerUrl))
                        && isDepthAcceptable(crawlerUrl)) {
                    nextUrl = crawlerUrl;
                    //System.out.println("Le prochain url a visiter est "+nextUrl);
                }
            }
            return nextUrl;
        }
     
        // maintenant il y a quelques methodes auxiliaires 
     
        private void printCrawlInfo() throws Exception {
        	int nb=getNumberOfUrlsVisited();
        	if(nb!=0 && nb % 100 ==0)
        	{
        		Applet_VeilleConcurentielle.console("Crawling en cours... "+nb+" URL analysés    /    Crawling in progress... "+nb+" URL visited      --     "+Fc.aujourdhui("dd/MM/yyyy HH:mm:ss"));
        	}
            /* StringBuilder sb = new StringBuilder();
            sb.append("Queue length = ").append(this.urlQueue.size()).append(
                    " visited urls=").append(getNumberOfUrlsVisited()).append(
                    " site permissions=").append(this.sitePermissions.size());
            System.out.println(sb.toString()); */
        }
     
        private int getNumberOfUrlsVisited() {
            return this.visitedUrls.size();
        }
     
        private boolean isDepthAcceptable(CrawlerUrl crawlerUrl) {
            return crawlerUrl.getDepth() <= this.maxDepth;
        }
     
        private boolean isUrlAlreadyVisited(CrawlerUrl crawlerUrl) {
            if ((crawlerUrl.isVisited())
    	    || (this.visitedUrls.contains(crawlerUrl.getUrlString()))) {
                return true;
            }
            return false;
        }
     
        public boolean doWeHavePermissionToVisit(CrawlerUrl crawlerUrl) {
            if (crawlerUrl == null) {
                return false;
            }
            if (!crawlerUrl.isCheckedForPermission()) {
                crawlerUrl.setAllowedToVisit(
    		computePermissionForVisiting(crawlerUrl));
            }
            // We need to check
            return crawlerUrl.isAllowedToVisit();
        }
     
     
        private boolean computePermissionForVisiting(CrawlerUrl crawlerUrl) {
            URL url = crawlerUrl.getURL();
            boolean retValue = (url != null);
            if (retValue) {
                String host  = url.getHost();
            if(!host.equals(domaineSite)) return false; //rester dans le domaine
            if(!crawlerUrl.extensionAutoriser(extensions)) return false; //extensions autorisées
    	    String port  = "";
    	    int    portN = url.getPort();
    	    if(portN > -1) {
    		port = ":" + String.valueOf(portN);
    	    }
                Collection<String> disallowedPaths=this.sitePermissions.get(host);
                if (disallowedPaths == null) {
                    disallowedPaths = 
    		    parseRobotsTxtFileToGetDisallowedPaths(host+port);
                }
                // On itere pour tous les chemins interdits (disallowed paths)
                String path = url.getPath();
                if(path!="" && path!="/")
                {
    	            for (String disallowedPath : disallowedPaths) {
    	                if (path.equals(disallowedPath)) {
    	                    retValue = false;
    	                }
    	            }
                }
            }
            return retValue;
        }
     
        private Collection<String> parseRobotsTxtFileToGetDisallowedPaths(
                String host) {
            String robotFilePath = getContent("http://" + host + "/robots.txt");
            Collection<String> disallowedPaths = new ArrayList<String>();
            if (robotFilePath != null) {
                Pattern p = Pattern.compile(USER_AGENT);
                String[] permissionSets = p.split(robotFilePath);
                String permissionString = "";
                for (String permission : permissionSets) {
                    if (permission.trim().startsWith("*")) {
                        permissionString = permission.substring(1);
                    }
                }
                p = Pattern.compile(DISALLOW);
                String[] items = p.split(permissionString);
                for (String s : items) {
                    disallowedPaths.add(s.trim());
                    // System.out.println(s.trim());
                }
            }
            this.sitePermissions.put(host, disallowedPaths);
            return disallowedPaths;
        }
     
        private String getContent(String urlString) {
            return getContent(new CrawlerUrl(urlString, 0));
        }
     
        private String getContent(CrawlerUrl url) { // methode essentielle -- 
            // recuperation du fichier .html depuis le serveur
    	HttpClient httpclient = new DefaultHttpClient();
    	String userAgent = this.userAgent;
    	httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, userAgent);
    	String text = new String();
            try {
                HttpGet httpget = new HttpGet(url.getUrlString()); //construction
    	    //  de l'objet qui fera la connexion
     
                //System.out.println("executing request " + httpget.getURI());
                // construction de l'objet qui gerera le dialogue avec le serveur 
                ResponseHandler<String> responseHandler = 
    		new BasicResponseHandler();
                try {
                text = httpclient.execute(httpget, responseHandler); //et on y va
                } catch(Exception e) {}
    	}
    	catch(Throwable t) {
    	    System.out.println("Echec du chargement de "+url.getUrlString()+" "+ t . toString());
    	    //t . printStackTrace();
    	}
    	finally {
                // Lorsque on n'a plus besoin de l'objet de type HttpClient
                // on ferme la connexion pour eliberer rapidement les resources
                // systeme qu'on avait monopolisees
                httpclient.getConnectionManager().shutdown();
            }
            markUrlAsVisited(url); // on marque l'URL
    	url . setRawContent(text); // on donne le texte HTML brut au parseur
    	// appele dans la classe CrawlerUrl -- qui en extrait le texte, 
    	// le titre, les liens sortants, etc. (apres avoir parse le texte 
    	// HTML ainsi fourni)
            return text;
     
        }
     
        private void markUrlAsVisited(CrawlerUrl url) {
            this.visitedUrls.add(url.getUrlString());
            url.setIsVisited();
        }
     
        private void saveContent(CrawlerUrl url)  throws Exception {
    		String content = url . getHTML();
    		//String title   = url . getTitle();
    		String urlPage = url . getUrlString();
     
     
    		String titre=Fc.trouverTxt(regexTitre, content,numMasqueTitre);
    		String prix=Fc.trouverTxt(regexPrix, content,numMasquePrix);
     
     
    		if(titre!=null && titre!="" && prix!=null && prix!="")
    		{
    			Produit pr=new Produit();
    			pr.setName(titre);
    			pr.setPrix(prix);
    			pr.lien=urlPage;
     
    			if(Applet_VeilleConcurentielle.pileProduitCourante!=null) Applet_VeilleConcurentielle.pileProduitCourante.aj(pr);
    		}
     
     
     
    		url.raz();
     
        }
     
        private void saveLinks(CrawlerUrl url) throws Exception {
        	//sauvegarder liens
        }
     
        private void addUrlsToUrlQueue(CrawlerUrl url) {
    	Collection<String> urlStrings = url . getLinks();
            int depth = url.getDepth() + 1;
            for (String urlString : urlStrings) {
                if (!this.visitedUrls.contains(urlString)) {
                     this.urlQueue.add(new CrawlerUrl(urlString, depth));
                }
            }
        }
     
        private void generateOutlinksIds() throws Exception{
        	//la méthode semble innutile
        }
    }
    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
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    package netsur2;
    import java.net.MalformedURLException;
    import java.net.URL;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
     
    import java.util.*;
     
    public class CrawlerUrl {
        // donnees et methodes pour l'URL elle-meme (en tant qu'"addresse web")
     
        private int depth = 0;
        private String urlString = null;
        private URL url = null;
        private boolean isAllowedToVisit;
        private boolean isCheckedForPermission = false;
        private boolean isVisited = false;
     
        public CrawlerUrl(String urlString, int depth) {
            this.depth = depth;
            this.urlString = urlString;
            computeURL();
        }
     
        private void computeURL() {
        	int isDiese=urlString.indexOf("#");
        	if (isDiese>-1) urlString=urlString.substring(0, isDiese);
            try {
                url = new URL(urlString);
            } catch (MalformedURLException e) {
    	    // petit probleme
            }
        }
     
        public URL getURL() {
            return this.url;
        }
     
        public int getDepth() {
            return this.depth;
        }
     
        public boolean isAllowedToVisit() {
            return isAllowedToVisit;
        }
     
        public void setAllowedToVisit(boolean isAllowedToVisit) {
            this.isAllowedToVisit = isAllowedToVisit;
            this.isCheckedForPermission = true;
        }
     
        public boolean isCheckedForPermission() {
            return isCheckedForPermission;
        }
     
        public boolean isVisited() {
            return isVisited;
        }
     
        public void setIsVisited() {
            this.isVisited = true;
        }
     
        public String getUrlString() {
            return this.urlString;
        }
     
        @Override
        public String toString() {
            return this.urlString + " [depth=" + depth + " visit="
                    + this.isAllowedToVisit + " check="
                    + this.isCheckedForPermission + "]";
        }
     
        @Override
        public int hashCode() {
            return this.urlString.hashCode();
        }
     
        @Override
        public boolean equals(Object obj) {
            return obj.hashCode() == this.hashCode();
        }
     
        // donnees et methodes concernant le contenu telecharge depuis l'URL
     
        private String       htmlText;
        private Document     htmlJsoupDoc;
        private String       niceText;
        private String       title;
        private List<String> linkList;
     
        public String getHTML() {
    	return(htmlText);
        }
     
        public String getNiceText() {
    	return(niceText);
        }
     
        public String getTitle() {
    	return(title);
        }
     
        public List<String> getLinks() {
    	return(linkList);
        }
     
        public void raz()
        {
        	htmlJsoupDoc=null;
        	htmlText=null;
        	niceText=null;
        	title=null;
        }
     
        public void setRawContent(String htmlText) {
    	String baseURL  = getURL() . toExternalForm();
    	this . htmlText = htmlText;
    	htmlJsoupDoc    = Jsoup . parse(htmlText,baseURL);
    	title           = htmlJsoupDoc . title();
    	//niceText        = htmlJsoupDoc . body() . text();
    	linkList        = new ArrayList<String>();
    	Elements hrefJsoupLinks = htmlJsoupDoc . select("a[href]");
            for (Element link : hrefJsoupLinks) {
    	    String thisLink = link.attr("abs:href");
    	    if(thisLink . startsWith("http://")) {
    		//System.out.println("JSOUP Found: " + thisLink);
    		linkList . add(thisLink);
    	    }
    	}		
        }
     
        public boolean extensionAutoriser(ArrayList<String> refuser)
        {
        	String path=url.getPath().toLowerCase();
        	for(String ext:refuser)
        	{
        		if(path.endsWith(ext)) return false;
        	}
        	return true;
        }
     
    }

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    En analysant le code, je ne vois plus rien qui me saute au yeux. Les char[]sont vraisemblablement référencés par les String. Il faut continuer avec le profiler à remonter, voir qui possède ces strings, qui possède les objets qui contients ces derniers, etc jusqu'à atteindre une variable qui est dans ton code, et tu saura qui est responsable de cette fuite de mémoire

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    676
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 676
    Points : 121
    Points
    121
    Par défaut
    Pour info j'ai fini par trouver la fuite de mémoire.
    En fait le crawler empilait tout les url qu'il trouvait dans un tableau et ensuite ils n'étaient pas vérifiés si déjà visités. Mais il y avait beaucoup de chose qui s'empilait pour rien.
    J'ai évacué le soucis en vérifiant que l'url n'était pas déjà présent.

    La méthodologie que j'ai utilisé est de mettre un Watch (inspecteur d'expression) sur tous mes tableaux. Par exemple j'entrais l'expression monArray.size() et j'arrêtais l'algo tout les 1000 url pour voir ce qui grossissait car on a pas le détail avec le profiler.

    Merci pour ton aide en tout cas.

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

Discussions similaires

  1. Dépassement de mémoire avec Rave 10.0.0
    Par benleq dans le forum Rave
    Réponses: 5
    Dernier message: 19/07/2012, 15h15
  2. Problème de mémoire avec BDE
    Par Machuet dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/07/2004, 10h11
  3. Problémes mémoire avec le bde sur des bases paradox
    Par Keke des Iles dans le forum Bases de données
    Réponses: 2
    Dernier message: 27/05/2004, 16h55
  4. Problème mémoire avec une dll par chargement dynamique
    Par widze19 dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/12/2003, 13h20
  5. Comment bien gerer la mémoire avec les TStringList?
    Par david_chardonnet dans le forum Langage
    Réponses: 5
    Dernier message: 18/06/2003, 09h57

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