2010-02-18 13 views
16

Simülasyonum aktörler ve Scala 2.8 Snapshot kullanıyor. Java JRE 1.5'de iyi çalışır - tüm 40 vites (oyuncu) aynı anda çalışır. Java JRE 1.6'yı kullanmak sadece 3 vites aynı anda çalışıyor. GUI ile ve GUI olmadan test ettim: her ikisi de aynı sonucu veriyor.Scala Aktörler: JRE 1.5 ve 1.6 üzerinde farklı davranış

GUI ile My simülasyon github geçerli:

http://github.com/pmeiclx/scala_gear_simulation Belki my first problem with actors unutmayın. Bu sorunları çözdükten sonra simülasyon için bir GUI yaptım ve bu yeni "garip" davranışı aldım.

İşte GUI olmadan kod:

package ch.clx.actorversions 

import actors.Actor 
import actors.Actor._ 
import collection.mutable.ListBuffer 

case class ReceivedSpeed(gear: Gear) 
case object StartSync 

case class SyncGear(controller: GearController, syncSpeed: Int) 

object ActorVersion { 

    def main(args:Array[String]) = { 
    println("[App] start with creating gears") 
    val gearList = new ListBuffer[Gear]() 
    for (i <- 0 until 100) { 
     gearList += new Gear(i) 
    } 

    val gearController = new GearController(gearList) 

    gearController.start() 
    gearController ! StartSync 
    } 
} 

/** 
* CONTROLLER 
*/ 
class GearController(nGears: ListBuffer[Gear]) extends Actor { 
    private var syncGears = new ListBuffer[Gear] 
    private var syncSpeed = 0 
    def act = { 
    while(true) { 
     receive { 
     case StartSync => { 
      println("[Controller] Send commands for syncing to gears!") 
      var speeds = new ListBuffer[Int] 
      nGears.foreach(e => speeds += e.speed) 

      //Calc avg 
      //var avgSpeed = speeds.foldLeft(0)(_ + _)/speeds.length 
      //var avgSpeed = speeds.foldLeft(0) { (x, y) => x + y }/speeds.length 
      syncSpeed = (0/:speeds)(_ + _)/speeds.length //Average over all gear speeds 

      //TODO syncSpeed auf Median ausrichten 

      println("[Controller] calculated syncSpeed: "+syncSpeed) 
      nGears.foreach{e => 
         e.start() 
         e ! SyncGear(this, syncSpeed) 
      } 
      println("[Controller] started all gears") 
     } 
     case ReceivedSpeed(gear: Gear) => { 
      println("[Controller] Syncspeed received by a gear ("+gear.gearId+")") 
      //println("[Controller] mailboxsize: "+self.mailboxSize) 
      syncGears += gear 
      if(syncGears.length == nGears.length) { 
      println("[Controller] all gears are back in town!") 
      System.exit(0) 
      } 
     } 
     case _ => println("[Controller] No match :(") 
     } 
    } 
    } 
} 

/** 
* GEAR 
*/ 
class Gear(id: Int) extends Actor { 

    private var mySpeed = scala.util.Random.nextInt(1000) 
    private var myController: GearController = null 

    def speed = mySpeed 
    def gearId = id 

    /* Constructor */ 
    println("[Gear ("+id+")] created with speed: "+mySpeed) 

    def act = { 
    loop { 
     react { 
     case SyncGear(controller: GearController, syncSpeed: Int) => { 
      //println("[Gear ("+id+")] activated, try to follow controller command (form mySpeed ("+mySpeed+") to syncspeed ("+syncSpeed+")") 
      myController = controller 
      adjustSpeedTo(syncSpeed) 
     } 
     } 
    } 
    } 

    def adjustSpeedTo(targetSpeed: Int) = { 
    if(targetSpeed > mySpeed) { 
     mySpeed += 1 
     self ! SyncGear(myController, targetSpeed) 
    }else if(targetSpeed < mySpeed) { 
     mySpeed -= 1 
     self ! SyncGear(myController, targetSpeed) 
    } else if(targetSpeed == mySpeed) { 
     callController 
    } 
    } 

    def callController = { 
    println("[Gear ("+id+")] has syncSpeed") 
    myController ! ReceivedSpeed(this) 
    } 
} 

cevap

8

Kısa cevap:

aktörler üzerinde çalıştığı Java sürümü kütüphane algılar/alma yerine süre içinde tepki/döngü kullanmak için kumandayı değiştirmek ve 1.6 ise (ve IBM'in VM) kullandığı bir JSR-166y çatal birleştirme iş parçacığı havuzunun birleştirilmiş sürümü, bu nedenle Java sürümüne bağlı olarak temel uygulamada önemli bir fark vardır.

Çatal/birleştirme iş parçacığı havuzu, görevler için bir iki düzey sıra kullanır.Her çalışan iş parçacığı bir sırası vardır ve havuz için ortak kuyruk var. çatalla menşeli Görevler/iplik/çatal üzerine doğrudan gitmek yerine ana kuyruğu ile daha parçacığının kuyruğa katılmak katılmak. parçacıkları arasında çalarak Görev meşgul konuları tutmak ve açlık önlemek için kullanılır. Senin durumunda

görevlerin tümünü dişliler kontrolörü çalışan iş parçacığı için sıraya sona başlatın. Eğer süre kullanarak Çünkü/o dişin asla bırakmaz o aktör aldığımız, bu yüzden asla onun kuyruğunda doğrudan görevleri yürütür. Diğer iplikler 3 vitesli sürekli meşgul, bu nedenle denetleyici çalıştıran iplikten çalışmalarını çalmak girişimi olmadı. Sonuç, diğer dişli aktörlerin hiçbir zaman idam edilmemesidir.

Denetleyicide döngü/tepki moduna geçilmesi sorunu özer, çünkü her döngüde aktör iş parçacığından ayrılır ve sıradaki diğer görevler, bu sırada diğer görevlerin sona ereceği yeni bir görev zamanlar. yürütülür.

+0

FYI: Bu problemi Philipp Haller'a anlattım ve o bunu bagaja yerleştirdi. Yani 2.8 yayınlandığında sorun olmaz. https://lampsvn.epfl.ch/trac/scala/changeset/20950/scala/trunk/src/actors –

+0

Üzgünüz, biraz meşguldüm. Yeni Snapshot ile çalışır. Mükemmel değil ama işe yarıyor. Teşekkür ederim! – meip

1

sadece 3 dişliler aynı anda çalışıyoruz Java JRE 1.6 kullanma.

  • sadece üç dişli hedef hızının yolunda herhangi bir ilerleme olun:

bunu mu demek istiyorsunuz. Üç vites hedef hıza ulaştığında, daha fazla viteste ilerleme olmaz.
  • sadece üç dişli herhangi bir zamanda ilerleme kaydetmektedir. Üç vitesten biri hedef hıza ulaştığında, diğer dişliler tüm hızlar hedef hıza ulaşana kadar ilerlemeye başlar.
  • Sanırım ikinci olur mu?

    Gözlemlenen davranıştaki fark, muhtemelen JVM uygulamalarındaki bir fark kadardır - JRE 1.5 ve JRE 1.6 arasında değişiklikler vardır. Bu değişikliklerin bazıları kapatılabilir, ör.

    -XX:ThreadPriorityPolicy=1 
    

    ... ama ikinci davranış kodu çalıştırmak için tamamen geçerli yoludur: bunun gibi bir bayrağı ayarlayarak. Beklediğiniz şey değil, çünkü sahip olduğunuz "adalet" kavramını ihlal ediyor, ancak iş planlayıcısı bunu yapmıyor. En çok tercih edilen teçhizatın en az tercih edilen aktörden daha fazla (10) "keneler" ten fazla olmamasını sağlamak için bir çeşit Saat aktörü ekleyebilirsiniz.

    JRE arasındaki fark bilmeden araştırmaya zordur:

    • tam olarak kullanmakta olduğunuz JRE güncelleme sürümleri. Çalıştığınız işletim sistemi
    • .
    • Kaç tane işlemci ve çekirdek var. Kod JRE 1.6 için yeniden derlenmiş olup olmadığına dair
    • .

    İyi şanslar!

    İlgili konular