Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 邮箱溢出。斯卡拉_Memory_Scala_Memory Management_Actor - Fatal编程技术网

Memory 邮箱溢出。斯卡拉

Memory 邮箱溢出。斯卡拉,memory,scala,memory-management,actor,Memory,Scala,Memory Management,Actor,我目前在scala与两名演员合作。其中一个是生产者,产生一些数据并将其发送给包裹商。生产者通过消息发送一个HashMap[String,HashMap[Object,List[Int]]](与此一起标记发送者): 解析器一直在等待这样的消息: def act(){ loop{ react{ case (producer, data)=> parse(data); } } } 该程序在正常环境下运行良好。这个问题伴随着大量的数据和发送

我目前在scala与两名演员合作。其中一个是生产者,产生一些数据并将其发送给包裹商。生产者通过消息发送一个
HashMap[String,HashMap[Object,List[Int]]]
(与此一起标记发送者):

解析器一直在等待这样的消息:

def act(){
    loop{
      react{
        case (producer, data)=> parse(data);
      }
    }
}
该程序在正常环境下运行良好。这个问题伴随着大量的数据和发送的许多消息(散列大约有10^4个元素,内部散列大约有100个元素,列表有100个元素),程序崩溃。它既没有错误也没有例外。它只是停止了

问题似乎是我的生成器的工作速度比解析器快得多(目前我不需要多个解析器)

阅读之后,我想知道我的解析器的邮箱是否达到了极限。这篇文章也提供了一些解决方案,但我首先需要确定这就是问题所在。我如何测试这个

有没有办法知道演员的记忆力极限?读取邮箱中的已用/可用内存如何

欢迎对尚未发布的工作流提出任何建议


谢谢,

首先,您不需要显式地传递发送者,因为Scala actors框架仍然跟踪发送者。您始终可以使用方法
sender
访问邮件的发件人

从这里可以看到:,参与者的邮箱被实现为一个链表,因此只受堆大小的限制

不过,如果你担心生产者速度很快,消费者速度很慢,我建议你探索一种节流机制。但我不推荐这个问题的公认答案

一般来说,在系统压力很大的情况下发送过载消息似乎不是一个好主意。如果您的系统太忙而无法检查过载,该怎么办?如果过载消息的接收者太忙而无法对其执行操作,该怎么办?而且,对我来说,删除消息听起来不是个好主意。我认为您希望所有工作项都得到可靠的处理

此外,我不会依赖
mailboxSize
来确定负载。您无法区分不同的消息类型,只能从使用者本身进行检查,而不能从生产者进行检查

我建议使用一种方法,当消费者知道他可以处理时,他会要求更多的工作

下面是一个如何实现它的简单示例

import scala.actors._
import Actor._

object ConsumerProducer {
  def main(args: Array[String]) {
    val producer = new Producer(Iterator.range(0, 10000))
    val consumer = new Consumer(producer)
  }
}

case class Produce(count: Int)
case object Finished

class Producer[T](source: Iterator[T]) extends Actor {

  start

  def act() {
    loopWhile(source.hasNext) {
      react {
        case Produce(n: Int) => produce(n)
      } 
    }
  }

  def produce(n: Int) {
    println("producing " + n)
    var remaining = n
    source takeWhile(_ => remaining > 0) foreach { x => sender ! x; remaining -= 1 }
    if(!source.hasNext) sender ! Finished
  }
}

class Consumer(producer: Actor) extends Actor {

  start

  private var remaining = 0

  def act() {
    requestWork()
    consume()
  }

  def consume(): Nothing = react {
    case Finished => println("Finished")
    case n: Int => work(n); requestWork(); consume()
  }

  def requestWork() = if(remaining < 5) { remaining += 10; producer ! Produce(10) }

  def work(n: Int) = {
    println(n + ": " + (0 until 10000).foldLeft(0) { (acc, x) => acc + x * n })
    remaining -= 1
  }
}
导入scala.actors_
重要演员_
对象使用者生产者{
def main(参数:数组[字符串]){
val producer=新的producer(迭代器范围(0,10000))
val消费者=新消费者(生产者)
}
}
案例类产品(计数:Int)
案例对象已完成
类生产者[T](来源:迭代器[T])扩展了参与者{
开始
def法案(){
loopWhile(source.hasNext){
反应{
案例产品(n:Int)=>产品(n)
} 
}
}
def产品(n:Int){
println(“生产”+n)
剩余var=n
source takeWhile(=>remaining>0)foreach{x=>sender!x;remaining-=1}
如果(!source.hasNext)发件人!已完成
}
}
类使用者(生产者:Actor)扩展了Actor{
开始
私有变量剩余=0
def法案(){
请求工作()
消费()
}
def consume():Nothing=react{
案例完成=>println(“完成”)
案例n:Int=>work(n);requestWork();consume()
}
def requestWork()=if(剩余<5){剩余+=10;生产者!生产者(10)}
def工作(n:Int)={
println(n+”:“+(0到10000)。foldLeft(0){(acc,x)=>acc+x*n})
剩余-=1
}
}

你好,鲁迪格,谢谢你的回答。所以邮箱没有像我想的那样实现!顺便说一句,你如何访问消息的发送者?在你的actor中你有发送者方法。它总是返回最后收到的邮件的发件人。在我给出的示例中,我在Producer-actor的production方法中使用了它。如果你想看看不同的实现,你应该看看Akka[1],它既有负载平衡[2]又有工作窃取[3][1]:www.akkasource.org[2]:[3]:
import scala.actors._
import Actor._

object ConsumerProducer {
  def main(args: Array[String]) {
    val producer = new Producer(Iterator.range(0, 10000))
    val consumer = new Consumer(producer)
  }
}

case class Produce(count: Int)
case object Finished

class Producer[T](source: Iterator[T]) extends Actor {

  start

  def act() {
    loopWhile(source.hasNext) {
      react {
        case Produce(n: Int) => produce(n)
      } 
    }
  }

  def produce(n: Int) {
    println("producing " + n)
    var remaining = n
    source takeWhile(_ => remaining > 0) foreach { x => sender ! x; remaining -= 1 }
    if(!source.hasNext) sender ! Finished
  }
}

class Consumer(producer: Actor) extends Actor {

  start

  private var remaining = 0

  def act() {
    requestWork()
    consume()
  }

  def consume(): Nothing = react {
    case Finished => println("Finished")
    case n: Int => work(n); requestWork(); consume()
  }

  def requestWork() = if(remaining < 5) { remaining += 10; producer ! Produce(10) }

  def work(n: Int) = {
    println(n + ": " + (0 until 10000).foldLeft(0) { (acc, x) => acc + x * n })
    remaining -= 1
  }
}