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

斯卡拉 – 阿卡消息传递时间

发布时间:2020-12-16 18:28:35 所属栏目:安全 来源:网络整理
导读:我正在与 Scala和Akka一起进行人工生命模拟,到目前为止,我对两者都非常满意.我有一些时间问题,但我无法解释. 目前,我模拟的每只动物都是一对演员(动物大脑).通常,这两个演员轮流(动物将传感器输入发送到大脑,等待结果,作用于它并重新开始).然而,不时地,动物
我正在与 Scala和Akka一起进行人工生命模拟,到目前为止,我对两者都非常满意.我有一些时间问题,但我无法解释.

目前,我模拟的每只动物都是一对演员(动物大脑).通常,这两个演员轮流(动物将传感器输入发送到大脑,等待结果,作用于它并重新开始).然而,不时地,动物需要彼此互动以互相吃饭或繁殖.

对我来说奇怪的一件事是时机.事实证明,从一只动物向另一只动物发送信息比从动物发送到大脑要慢很多(大约100倍).这使得我的可怜的食肉动物和性活跃的动物处于劣势,而不是素食者和无性动物(免责声明:我自己也吃素,但我认为成为素食主义者的理由比在尝试捕食时陷入困境更好. ).

我提取了一个演示问题的最小代码片段:

package edu.blindworld.test

import java.util.concurrent.TimeUnit

import akka.actor.{ActorRef,ActorSystem,Props,Actor}
import akka.pattern.ask
import akka.util.Timeout

import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.Random

class Animal extends Actor {
  val brain = context.actorOf(Props(classOf[Brain]))
  var animals: Option[List[ActorRef]] = None

  var brainCount = 0
  var brainRequestStartTime = 0L
  var brainNanos = 0L

  var peerCount = 0
  var peerRequestStartTime = 0L
  var peerNanos = 0L

  override def receive = {
    case Go(all) =>
      animals = Some(all)
      performLoop()
    case BrainResponse =>
      brainNanos += (System.nanoTime() - brainRequestStartTime)
      brainCount += 1
      // Animal interactions are rare
      if (Random.nextDouble() < 0.01) {
        // Send a ping to a random other one (or ourselves). Defer our own loop
        val randomOther = animals.get(Random.nextInt(animals.get.length))
        peerRequestStartTime = System.nanoTime()
        randomOther ! PeerRequest
      } else {
        performLoop()
      }
    case PeerResponse =>
      peerNanos += (System.nanoTime() - peerRequestStartTime)
      peerCount += 1
      performLoop()
    case PeerRequest =>
      sender() ! PeerResponse
    case Stop =>
      sender() ! StopResult(brainCount,brainNanos,peerCount,peerNanos)
      context.stop(brain)
      context.stop(self)
  }

  def performLoop() = {
    brain ! BrainRequest
    brainRequestStartTime = System.nanoTime()
  }
}

class Brain extends Actor {
  override def receive = {
    case BrainRequest =>
      sender() ! BrainResponse
  }
}

case class Go(animals: List[ActorRef])
case object Stop
case class StopResult(brainCount: Int,brainNanos: Long,peerCount: Int,peerNanos: Long)

case object BrainRequest
case object BrainResponse

case object PeerRequest
case object PeerResponse

object ActorTest extends App {
  println("Sampling...")
  val system = ActorSystem("Test")
  val animals = (0 until 50).map(i => system.actorOf(Props(classOf[Animal]))).toList
  animals.foreach(_ ! Go(animals))
  Thread.sleep(5000)
  implicit val timeout = Timeout(5,TimeUnit.SECONDS)
  val futureStats = animals.map(_.ask(Stop).mapTo[StopResult])
  val stats = futureStats.map(Await.result(_,Duration(5,TimeUnit.SECONDS)))
  val brainCount = stats.foldLeft(0)(_ + _.brainCount)
  val brainNanos = stats.foldLeft(0L)(_ + _.brainNanos)
  val peerCount = stats.foldLeft(0)(_ + _.peerCount)
  val peerNanos = stats.foldLeft(0L)(_ + _.peerNanos)
  println("Average time for brain request: " + (brainNanos / brainCount) / 1000000.0 + "ms (sampled from " + brainCount + " requests)")
  println("Average time for peer pings: " + (peerNanos / peerCount) / 1000000.0 + "ms (sampled from " + peerCount + " requests)")
  system.shutdown()
}

这就是这里发生的事情:

>我正在创造50对动物/大脑演员
>它们全部启动并运行5秒钟
>每只动物都会进行无限循环,轮流使用它的大脑
>在所有跑步的1%中,动物向其他随机动物发送ping并等待其回复.然后,它继续与大脑循环
>测量对大脑和同伴的每个请求,以便我们得到平均值
> 5秒后,一切都停止,比较大脑请求和同伴ping的时间

在我的双核i7上,我看到这些数字:

Average time for brain request: 0.004708ms (sampled from 21073859 requests)

Average time for peer pings: 0.66866ms (sampled from 211167 requests)

因此对同行的ping比对大脑的要求慢165倍.我一直在尝试很多东西来解决这个问题(例如优先邮箱和热身JIT),但还是无法弄清楚发生了什么.有没有人有想法?

解决方法

我认为你应该使用ask模式来处理消息.在你的代码中,BrainRequest被发送给大脑演员,然后它发送回BrainResponse.问题出在这里. BrainResponse不是BrainRequest的回应.也许这是以前的BrainRequest的回应.

以下代码使用ask模式,perf结果几乎相同.

package edu.blindworld.test

import java.util.concurrent.TimeUnit

import akka.actor.{ActorRef,Actor}
import akka.pattern.ask
import akka.util.Timeout

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.util.Random

class Animal extends Actor {
  val brain = context.actorOf(Props(classOf[Brain]))
  var animals: Option[List[ActorRef]] = None

  var brainCount = 0
  var brainRequestStartTime = 0L
  var brainNanos = 0L

  var peerCount = 0
  var peerRequestStartTime = 0L
  var peerNanos = 0L

  override def receive = {
    case Go(all) =>
      animals = Some(all)
      performLoop()
    case PeerRequest =>
      sender() ! PeerResponse
    case Stop =>
      sender() ! StopResult(brainCount,peerNanos)
      context.stop(brain)
      context.stop(self)
  }

  def performLoop(): Unit = {
    brainRequestStartTime = System.nanoTime()
    brain.ask(BrainRequest)(10.millis) onSuccess {
      case _ =>
        brainNanos += (System.nanoTime() - brainRequestStartTime)
        brainCount += 1
        // Animal interactions are rare
        if (Random.nextDouble() < 0.01) {
          // Send a ping to a random other one (or ourselves). Defer our own loop
          val randomOther = animals.get(Random.nextInt(animals.get.length))
          peerRequestStartTime = System.nanoTime()
          randomOther.ask(PeerRequest)(10.millis) onSuccess {
            case _ =>
              peerNanos += (System.nanoTime() - peerRequestStartTime)
              peerCount += 1
              performLoop()
          }
        } else {
          performLoop()
        }
    }
  }
}

class Brain extends Actor {
  override def receive = {
    case BrainRequest =>
      sender() ! BrainResponse
  }
}

case class Go(animals: List[ActorRef])
case object Stop
case class StopResult(brainCount: Int,TimeUnit.SECONDS)))
  val brainCount = stats.foldLeft(0)(_ + _.brainCount)
  val brainNanos = stats.foldLeft(0L)(_ + _.brainNanos)
  val peerCount = stats.foldLeft(0)(_ + _.peerCount)
  val peerNanos = stats.foldLeft(0L)(_ + _.peerNanos)
  println("Average time for brain request: " + (brainNanos / brainCount) / 1000000.0 + "ms (sampled from " + brainCount + " requests)")
  println("Average time for peer pings: " + (peerNanos / peerCount) / 1000000.0 + "ms (sampled from " + peerCount + " requests)")
  system.shutdown()
}

(编辑:李大同)

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

    推荐文章
      热点阅读