Scalaな新年

新年早々、Scalaでの実験を繰り返す。
かなり、わかってきた。
200万のプロセス(Actor)をチェインしての実験などをしてみる。
ヒープのサイズを768M程度にしてやれば問題なく動く模様。

コンパイルが面倒になったので、
ついでにRakeの実習も兼ねられてラッキーな感じ。

import scala.actors._
import scala.actors.Actor._

object test extends Application {
  def make_actor(no:int, next:Actor):Actor = {
    actor {
      loop {
        react {
          case Tuple3('Hoge, i:int, t:Long) =>
            val now = System.nanoTime()
            val tm = now - t
            // println("Hoge" + no + ":" + i +":" + tm)
            if (next != null) next ! Tuple3('Hoge, i, t)
          case 'Stop =>
            if ( (no % 10000) == 0) println("STOP" + no + ":" + System.nanoTime())
            if (next != null) next ! 'Stop
            exit()
        }
      }
    }
  }

  def make_chain(n:int):List[Actor] = make_chain(n, null, List())
  def make_chain(n:int, next:Actor, chain:List[Actor]):List[Actor] = n match {
    case 0 => chain
    case _ => {
      val at = make_actor(n, next)
      make_chain(n-1, at, at :: chain)
    }
  }

  println("ScalaTest")
  println(System.nanoTime())
  val at_chain = make_chain(2000000)
  //  println(at_chain)
  println(System.nanoTime())
  val at = at_chain.head
  //  println(at)
  for (val i <- 0 until 10) {
    at ! Tuple3('Hoge, i, System.nanoTime())
  }
  at ! 'Stop
  println(System.nanoTime())
}
#---------------------------------------
# ディレクトリ指定

SRC_DIR   = 'src'
CLASS_DIR = 'classes'
LIB_DIR   = 'lib'

#===============================================================================
# 以下は共通設定
require 'rake/clean'

@opt = ''

#---------------------------------------
src_files = FileList["#{SRC_DIR}/**/*.scala"]
class_files = src_files.ext('class')
class_files.map!{|f| f.sub(/^#{SRC_DIR}/, CLASS_DIR)}

LIB_FILES = FileList["#{LIB_DIR}/*.jar"]
LIB_FILES.push(CLASS_DIR)

#---------------------------------------
def fsc_compile(source)
  sh "call fsc #{@opt} -classpath #{LIB_FILES.join(';')} -d #{CLASS_DIR} #{source}"
end

def run_class(mainclass)
  sh "call scala #{@opt} -classpath #{LIB_FILES.join(';')} #{mainclass}"
end

#---------------------------------------
task 'default' => :compile

#---------------------------------------
task :compile => class_files
task 'verbose_compile' => [:verbose] + class_files

#---------------------------------------
CLEAN.include(class_files)
CLEAN.include("#{CLASS_DIR}/*.class")

#---------------------------------------
task :verbose do
  @opt += ' -verbose'
end

#---------------------------------------
rule /^#{CLASS_DIR}\/.*.class$/ => [
  proc { |tn| tn.gsub(/^#{CLASS_DIR}/, SRC_DIR).ext('scala')}
] do |t|
  fsc_compile(t.source)
end

#---------------------------------------
class_files.each {|classfile|
  basename = File.basename(classfile, '.class')
  task basename => classfile do |t|
    run_class(t.name)
  end
}

#---------------------------------------