我正在使用带有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)
问题
有没有办法:
减少从段落中提取名词时使用的内存量。
使用Apache OpenNLP以外的其他api不会使用尽可能多的内存。
配置AWS Elastic Beanstalk Tomcat Server以应对需求的方法。
代码示例:
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:
答案 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)