2017-10-17 17 views
0

Je suis en train de lire et d'analyser un fichier de texte brut, en lisant ligne par ligne, en découpant chaque ligne en phrases, en divisant chaque phrase en mots et en les stockant dans la liste par phrase et par doc.Pourquoi la limite de surcharge GC est-elle dépassée?

Le fichier d'entrée contient 5 millions de lignes, donc je mis la taille de l'ArrayList être 5005000. Ma taille du tas dans IntelliJ est ci-dessous:

# custom IntelliJ IDEA VM options 

-Xms128m 
-Xmx8192m 
-XX:ReservedCodeCacheSize=240m 
-XX:+UseConcMarkSweepGC 
-XX:SoftRefLRUPolicyMSPerMB=50 
-ea 
-Dsun.io.useCanonCaches=false 
-Djava.net.preferIPv4Stack=true 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:-OmitStackTraceInFastThrow 

Mon ordinateur portable a 15G RAM. Après il lit 4500000 lignes (comme indiqué par l'instruction print), il devient alors très lent. Après quelques minutes, j'ai reçu:

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded 

Chaque ligne (analysable en un seul document) est court, donc ma mémoire 15G devrait être plus que suffisant pour le maintenir. La taille du fichier texte est seulement de 800 Mo. Pendant que je regarde mon moniteur de performance dans Windows 10, il montre seulement environ 55% de mémoire utilisée, ce qui indique qu'il y a encore beaucoup de mémoire disponible quand il meurt. Une note, dans le code ci-dessous, j'utilise 'phrase.toCharArray()', parce que ce n'est pas l'anglais, donc je traite fondamentalement chaque caractère comme un mot dans mon implémentation.

Seulement 5 millions de lignes, et pourquoi est-il mort?

 List<List<List<String>>> allWords = new ArrayList<>(5005000); 
     System.out.println("Load text from file: "); 
     try { 
      BufferedReader br = Utils.fileReader(filePath); 

      String line; 
      int lineNo = 0; 
      while ((line = br.readLine()) != null) { 
       List<List<String>> wordsPerDoc = new ArrayList<>(); 
       for (String sentence : segment(line)) { 
        List<String> wordsPerSentence = new ArrayList<>(); 
        for (Character c : sentence.toCharArray()) { 
         wordsPerClause.add(Character.toString(c)); 
        } 
        wordsPerDoc.add(wordsPerSentence); 
       } 
       allWords.add(wordsPerDoc); 
       lineNo++; 
       if(lineNo % 500000 ==0) { 
        System.out.println(lineNo); 
       } 
      } 
      System.out.println("Loaded text from file. "); 

      br.close(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (br != null) { 
       try { 
        br.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

public List<String> segment(final String line) { 
     List<String> sentences = new ArrayList<>(); 
     StringTokenizer tokenizer = new StringTokenizer(line, OtherConstants.BASIC_TOKENIZATION_DELIMITER, true); 
     while (tokenizer.hasMoreTokens()) { 
      String word = tokenizer.nextToken(); 
       sentences.add(word); 
     } 
     return sentences; 
    } 

Répondre

0

Vous changez le profil de mémoire pour IntelliJ.

Pour le modifier pour votre application: allez dans le menu déroulant en haut à droite; trouvez votre classe principale; cliquez sur "Modifier les configurations"; et définissez "Options VM" sur -Xmx4g pour un segment de mémoire de 4 Go pour votre application.

https://www.jetbrains.com/help/idea/run-debug-configuration-application.html pour les documents