加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么Akka应用程序在执行NLP任务时因内存不足错误而失

发布时间:2020-12-16 08:44:08 所属栏目:安全 来源:网络整理
导读:我注意到我的程序有严重的内存泄漏(内存消耗螺旋上升).我必须并行化这个NLP任务(使用StanfordNLP EnglishPCFG Parser和T regex Matcher).所以我构建了一个演员管道(每个任务只有6个演员): val listOfTregexActors = (0 to 5).map(m = system.actorOf(Props(
我注意到我的程序有严重的内存泄漏(内存消耗螺旋上升).我必须并行化这个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
https://github.com/windweller/parallelAkka/blob/master/src/main/scala/blogParallel/TregexActor.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?

编辑
请参阅 – 使用道具here创建演员

其他几件事情要考虑:

>确保你的演员没有死亡并自动重启.
>在actor之外创建NLP对象,并在创建actor时传递它们.
>使用Akka router而不是哈希逻辑来分配不同参与者之间的工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读