减少Java堆大小

时间:2017-03-28 06:14:21

标签: java amazon-web-services elastic-beanstalk opennlp

我正在使用带有Apache OpenNLP的Java8。我有一个服务,从段落中提取所有名词。这在我的localhost服务器上按预期工作。我也在OpenShift服务器上运行,没有任何问题。但是,它确实使用了大量内存。我需要将我的应用程序部署到AWS Elastic Beanstalk Tomcat Server

一种解决方案是我可以从AWS Elastic Beanstalk Tomcat Server t1.micro 升级到另一种实例类型。但我预算很少,如果可能的话,我想避免使用extra fees

当我运行应用程序时,它尝试执行单词分块,它会收到以下错误:

dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space] with root cause
 java.lang.OutOfMemoryError: Java heap space
  at opennlp.tools.ml.model.AbstractModelReader.getParameters(AbstractModelReader.java:148)
  at opennlp.tools.ml.maxent.io.GISModelReader.constructModel(GISModelReader.java:75)
  at opennlp.tools.ml.model.GenericModelReader.constructModel(GenericModelReader.java:59)
  at opennlp.tools.ml.model.AbstractModelReader.getModel(AbstractModelReader.java:87)
  at opennlp.tools.util.model.GenericModelSerializer.create(GenericModelSerializer.java:35)
  at opennlp.tools.util.model.GenericModelSerializer.create(GenericModelSerializer.java:31)
  at opennlp.tools.util.model.BaseModel.finishLoadingArtifacts(BaseModel.java:328)
  at opennlp.tools.util.model.BaseModel.loadModel(BaseModel.java:256)
  at opennlp.tools.util.model.BaseModel.<init>(BaseModel.java:179)
  at opennlp.tools.parser.ParserModel.<init>(ParserModel.java:180)
  at com.jobs.spring.service.lang.LanguageChunkerServiceImpl.init(LanguageChunkerServiceImpl.java:35)
  at com.jobs.spring.service.lang.LanguageChunkerServiceImpl.getNouns(LanguageChunkerServiceImpl.java:46)

问题

有没有办法:

  1. 减少从段落中提取名词时使用的内存量。

  2. 使用Apache OpenNLP以外的其他api不会使用尽可能多的内存。

  3. 配置AWS Elastic Beanstalk Tomcat Server以应对需求的方法。

  4. 代码示例:

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashSet;
    import java.util.Set;
    
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.annotation.Transactional;
    
    import opennlp.tools.cmdline.parser.ParserTool;
    import opennlp.tools.parser.Parse;
    import opennlp.tools.parser.Parser;
    import opennlp.tools.parser.ParserFactory;
    import opennlp.tools.parser.ParserModel;
    import opennlp.tools.util.InvalidFormatException;
    
    @Component("languageChunkerService")
    @Transactional
    public class LanguageChunkerServiceImpl implements LanguageChunkerService {
    
        private Set<String> nouns = null;
        private InputStream modelInParse = null;
        private ParserModel model = null;
        private Parser parser = null;
    
        public void init() throws InvalidFormatException, IOException {
            ClassLoader classLoader = getClass().getClassLoader();
            File file = new File(classLoader.getResource("en-parser-chunking.bin").getFile());
            modelInParse = new FileInputStream(file.getAbsolutePath());
    
            // load chunking model
            model = new ParserModel(modelInParse); // line 35
            // create parse tree
            parser = ParserFactory.create(model);
        }
    
        @Override
        public Set<String> getNouns(String sentenceToExtract) {
            Set<String> extractedNouns = new HashSet<String>();
            nouns = new HashSet<>();
            try {
                if (parser == null) {
                    init();
                }
    
                Parse topParses[] = ParserTool.parseLine(sentenceToExtract, parser, 1);
    
                // call subroutine to extract noun phrases
                for (Parse p : topParses) {
                    getNounPhrases(p);
                }
    
                // print noun phrases
                for (String s : nouns) {
                    String word = s.replaceAll("[^a-zA-Z ]", "").toLowerCase();// .split("\\s+");
                    //System.out.println(word);
                    extractedNouns.add(word);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (modelInParse != null) {
                    try {
                        modelInParse.close();
                    } catch (IOException e) {
                    }
                }
            }
            return extractedNouns;
        }
    
        // recursively loop through tree, extracting noun phrases
        private void getNounPhrases(Parse p) {
            if (p.getType().equals("NN")) { // NP=noun phrase
                // System.out.println(p.getCoveredText()+" "+p.getType());
                nouns.add(p.getCoveredText());
            }
            for (Parse child : p.getChildren())
                getNounPhrases(child);
        }
    }
    

    更新

    Tomcat8 config:

    enter image description here

1 个答案:

答案 0 :(得分:-1)

首先,您应该尝试优化代码。这是在使用replaceAll之前使用正则表达式和预编译语句开始的,因为replaceAll替换了内存中的东西。 (https://eyalsch.wordpress.com/2009/05/21/regex/

其次,您不应将已解析的句子存储在数组中。第三个提示:您应该尝试使用bytebuffer将内存分配给您的数组。另一个可能会影响你的提示,你应该使用BufferedReader来读取你的chunked文件。 (out of memory error, java heap space

在此之后你应该已经看到更少的内存使用量。如果这些提示没有帮助您,请提供内存转储/分配图。

还有一个提示:HashSet占用的内存比无序列表多5.5倍。 (Performance and Memory allocation comparision between List and Set