scala – 为什么Akka应用程序在执行NLP任务时因内存不足错误而失
我注意到我的程序有严重的内存泄漏(内存消耗螺旋上升).我必须并行化这个NLP任务(使用StanfordNLP EnglishPCFG Parser和T
regex Matcher).所以我构建了一个演员管道(每个任务只有6个演员):
val listOfTregexActors = (0 to 5).map(m => system.actorOf(Props(new TregexActor(timer,filePrinter)),"TregexActor" + m)) val listOfParsers = (0 to 5).map(n => system.actorOf(Props(new ParserActor(timer,listOfTregexActors(n),lp)),"ParserActor" + n)) val listOfSentenceSplitters = (0 to 5).map(j => system.actorOf(Props(new SentenceSplitterActor(listOfParsers(j),timer)),"SplitActor" + j)) 我的演员非常标准.他们需要保持活力来处理所有信息(沿途没有毒药).内存消耗量上升,而且我没有一个关于错误的线索.如果我运行单线程,内存消耗就可以了.我在某处读到,如果演员没有死,那么内部的任何东西都不会被释放.我应该手动释放东西吗? 有两个举重演员: https://github.com/windweller/parallelAkka/blob/master/src/main/scala/blogParallel/ParserActor.scala 我想知道它是否可能是Scala的关闭或其他保留太多信息的机制,GC不能以某种方式收集它. 这是TregexActor的一部分: def receive = { case Match(rows,sen) => println("Entering Pattern matching: " + rows(0)) val result = patternSearching(sen) filePrinter ! Print(rows :+ sen.toString,result) } def patternSearching(tree: Tree):List[Array[Int]] = { val statsFuture = search(patternFuture,tree) val statsPast = search(patternsPast,tree) List(statsFuture,statsPast) } def search(patterns: List[String],tree: Tree) = { val stats = Array.fill[Int](patterns.size)(0) for (i <- 0 to patterns.size - 1) { val searchPattern = TregexPattern.compile(patterns(i)) val matcher = searchPattern.matcher(tree) if (matcher.find()) { stats(i) = stats(i) + 1 } timer ! PatternAddOne } stats } 或者如果我的代码检出,可能是StanfordNLP解析器还是tregex匹配器的内存泄漏?是否存在手动释放内存的策略,或者我是否需要在一段时间后杀死这些actor并将其邮箱任务分配给新的actor以释放内存? (如果是这样,怎么样?) 经过一些与分析工具的挣扎,我终于能够将VisualVM与IntelliJ一起使用.这是快照. GC从未跑过. 另一个是堆转储: 管道摘要: 原始文件 – > SentenceSplit Actors(6) – >解析器演员(6) – > Tregex演员(6) – >文件输出演员(完成) 模式在Entry.scala文件中定义:https://github.com/windweller/parallelAkka/blob/master/src/main/scala/blogParallel/Entry.scala 解决方法
这可能不是正确答案,但我没有足够的空间在评论中写出来.
尝试在Companion对象中移动创建的actor. val listOfTregexActors = (0 to 5).map(m => system.actorOf(Props(new TregexActor(timer,"TregexActor" + m)) val listOfParsers = (0 to 5).map(n => system.actorOf(Props(new ParserActor(timer,"ParserActor" + n)) val listOfSentenceSplitters = (0 to 5).map(j => system.actorOf(Props(new SentenceSplitterActor(listOfParsers(j),"SplitActor" + j)) 或者不要使用new来创建你的演员. 我怀疑当你创建应用程序时,你正在关闭你的应用程序,这阻止了GC收集任何垃圾. 通过在进行更改后查看Visual VM上的堆,可以轻松验证是否存在此问题. 此外,耗尽内存需要多长时间,最大值是多少.堆内存你给你的JVM? 编辑 其他几件事情要考虑: >确保你的演员没有死亡并自动重启. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |