Reorganize code in subproject, add the http and benchmark projects

pull/1/merge
Thibault Duplessis 2012-02-26 20:58:58 +01:00
parent fb54c688d4
commit 54b70d4e8d
40 changed files with 197 additions and 26 deletions

View File

@ -0,0 +1,82 @@
package lila.benchmark
import annotation.tailrec
import com.google.caliper.Param
// a caliper benchmark is a class that extends com.google.caliper.Benchmark
// the SimpleScalaBenchmark trait does it and also adds some convenience functionality
class Benchmark extends SimpleScalaBenchmark {
// to make your benchmark depend on one or more parameterized values, create fields with the name you want
// the parameter to be known by, and add this annotation (see @Param javadocs for more details)
// caliper will inject the respective value at runtime and make sure to run all combinations
@Param(Array("10"))
val length: Int = 0
var array: Array[Int] = _
override def setUp() {
// set up all your benchmark data here
array = new Array(length)
}
// the actual code you'd like to test needs to live in one or more methods
// whose names begin with 'time' and which accept a single 'reps: Int' parameter
// the body of the method simply executes the code we wish to measure, 'reps' times
// you can use the 'repeat' method from the SimpleScalaBenchmark trait to repeat with relatively low overhead
// however, if your code snippet is very fast you might want to implement the reps loop directly with 'while'
def timeForeach(reps: Int) = repeat(reps) {
//////////////////// CODE SNIPPET ONE ////////////////////
var result = 0
array.foreach {
result += _
}
result // always have your snippet return a value that cannot easily be "optimized away"
//////////////////////////////////////////////////////////
}
// a second benchmarking code snippet
def timeTFor(reps: Int) = repeat(reps) {
//////////////////// CODE SNIPPET TWO ////////////////////
var result = 0
tfor(0)(_ < array.length, _ + 1) { i =>
result += array(i)
}
result
//////////////////////////////////////////////////////////
}
// and a third benchmarking code snippet
def timeWhile(reps: Int) = repeat(reps) {
//////////////////// CODE SNIPPET THREE ////////////////////
var result = 0
var i = 0
while (i < array.length) {
result += array(i)
i = i + 1
}
result
//////////////////////////////////////////////////////////
}
// this is a scala version of Javas "for" loop, we test it against the array.foreach and a plain "while" loop
@tailrec
final def tfor[@specialized T](i: T)(test: T => Boolean, inc: T => T)(f: T => Unit) {
if(test(i)) {
f(i)
tfor(inc(i))(test, inc)(f)
}
}
override def tearDown() {
// clean up after yourself if required
}
}

View File

@ -0,0 +1,15 @@
package lila.benchmark
import com.google.caliper.{Runner => CaliperRunner}
object Runner {
// main method for IDEs, from the CLI you can also run the caliper Runner directly
// or simply use SBTs "run" action
def main(args: Array[String]) {
// we simply pass in the CLI args,
// we could of course also just pass hardcoded arguments to the caliper Runner
CaliperRunner.main(classOf[Benchmark], args: _*)
}
}

View File

@ -0,0 +1,21 @@
package lila.benchmark
import com.google.caliper.SimpleBenchmark
trait SimpleScalaBenchmark extends SimpleBenchmark {
// helper method to keep the actual benchmarking methods a bit cleaner
// your code snippet should always return a value that cannot be "optimized away"
def repeat[@specialized A](reps: Int)(snippet: => A) = {
val zero = 0.asInstanceOf[A] // looks wierd but does what it should: init w/ default value in a fully generic way
var i = 0
var result = zero
while (i < reps) {
val res = snippet
if (res != zero) result = res // make result depend on the benchmarking snippet result
i = i + 1
}
result
}
}

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package format
trait Format[A] {

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package format
import model._

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
import Pos.makePos

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
import Pos._

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
sealed trait Color {

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
case class Game(

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
case class History(

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
case class Piece(color: Color, role: Role) {

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
import scala.math.{ abs, min, max }

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
import Pos._

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
sealed trait Side {

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package model
case class Situation(board: Board, color: Color) {

View File

@ -1,4 +1,4 @@
package lila
package lila.chess
package object model {

View File

@ -1,9 +1,10 @@
package lila
import ornicar.scalalib._
package object lila
package object chess
extends OrnicarValidation
with OrnicarCommon
//with DateTime
with scalaz.Identitys
with scalaz.Equals
with scalaz.MABs

View File

@ -1,4 +1,4 @@
package lila
package lila.http
object Cli {

View File

@ -1,4 +1,4 @@
package lila
package lila.http
import repo._
import com.mongodb.casbah.MongoConnection

View File

@ -3,36 +3,72 @@ import Keys._
trait Resolvers {
val codahale = "repo.codahale.com" at "http://repo.codahale.com/"
//val twitter = "twitter.com" at "http://maven.twttr.com/"
val typesafe = "typesafe.com" at "http://repo.typesafe.com/typesafe/releases/"
val typesafeSnapshot = "typesafe.com snapshots" at "http://repo.typesafe.com/typesafe/snapshots/"
val typesafeS = "typesafe.com snapshots" at "http://repo.typesafe.com/typesafe/snapshots/"
val iliaz = "iliaz.com" at "http://scala.iliaz.com/"
val sonatype = "sonatype" at "http://oss.sonatype.org/content/repositories/releases"
val sonatypeS = "sonatype snapshots" at "http://oss.sonatype.org/content/repositories/snapshots"
}
trait Dependencies {
val twitterUtilVersion = "1.12.12"
val twitterCore = "com.twitter" % "util-core" % twitterUtilVersion
val slf4jNop = "org.slf4j" % "slf4j-nop" % "1.6.4"
val scalaz = "org.scalaz" %% "scalaz-core" % "6.0.4"
val specs2 = "org.specs2" %% "specs2" % "1.8.2"
val redis = "net.debasishg" %% "redisclient" % "2.4.2"
val json = "net.liftweb" %% "lift-json" % "2.4-RC1"
val casbah = "com.mongodb.casbah" %% "casbah" % "2.1.5-1"
val salat = "com.novus" %% "salat-core" % "0.0.8-SNAPSHOT"
val slf4jNop = "org.slf4j" % "slf4j-nop" % "1.6.4"
val instrumenter = "com.google.code.java-allocation-instrumenter" % "java-allocation-instrumenter" % "2.0"
val gson = "com.google.code.gson" % "gson" % "1.7.1"
}
object ApplicationBuild extends Build with Resolvers with Dependencies {
val lila = Project("lila", file("."), settings = Project.defaultSettings).settings(
libraryDependencies := Seq(scalaz, specs2, redis, json, casbah, salat),
resolvers := Seq(codahale, typesafe, typesafeSnapshot, iliaz, sonatype),
lazy val chess = Project("chess", file("chess"), settings = Project.defaultSettings).settings(
libraryDependencies := Seq(scalaz, specs2),
resolvers := Seq(codahale, sonatype),
shellPrompt := ShellPrompt.buildShellPrompt,
scalacOptions := Seq("-deprecation", "-unchecked")
) dependsOn (ornicarScalalib)
lazy val http = Project("http", file("http"), settings = Project.defaultSettings).settings(
libraryDependencies := Seq(scalaz, specs2, redis, json, casbah, salat),
resolvers := Seq(codahale, typesafe, typesafeS, iliaz, sonatype),
shellPrompt := ShellPrompt.buildShellPrompt,
scalacOptions := Seq("-deprecation", "-unchecked")
) dependsOn (chess, ornicarScalalib)
lazy val benchmark = Project("benchmark", file("benchmark"), settings = Project.defaultSettings).settings(
fork in run := true,
libraryDependencies := Seq(instrumenter, gson),
resolvers := Seq(codahale, sonatype),
shellPrompt := ShellPrompt.buildShellPrompt,
scalacOptions := Seq("-deprecation", "-unchecked"),
// we need to add the runtime classpath as a "-cp" argument
// to the `javaOptions in run`, otherwise caliper
// will not see the right classpath and die with a ConfigurationException
// unfortunately `javaOptions` is a SettingsKey and
// `fullClasspath in Runtime` is a TaskKey, so we need to
// jump through these hoops here in order to
// feed the result of the latter into the former
onLoad in Global ~= { previous => state =>
previous {
state get key match {
case None =>
// get the runtime classpath, turn into a colon-delimited string
val classPath = Project.runTask(fullClasspath in Runtime, state).get._2.toEither.right.get.files.mkString(":")
// return a state with javaOptionsPatched = true and javaOptions set correctly
Project.extract(state).append(Seq(javaOptions in run ++= Seq("-cp", classPath)), state.put(key, true))
case Some(_) => state // the javaOptions are already patched
}
}
}
) dependsOn (chess)
lazy val ornicarScalalib = uri("git://github.com/ornicar/scalalib#1.6")
// attribute key to prevent circular onLoad hook
val key = AttributeKey[Boolean]("javaOptionsPatched")
}
object ShellPrompt {

16
routes 100644
View File

@ -0,0 +1,16 @@
lichess_move ANY /move/{id}
lichess_say ANY /talk/{id}
lichess_resign ANY /resign/{id}
lichess_abort ANY /abort/{id}
lichess_outoftime ANY /outoftime/{id}
lichess_rematch ANY /rematch/{id}
lichess_force_resignation ANY /force-resign/{id}
lichess_claim_draw ANY /claim-draw/{id}
lichess_offer_draw ANY /offer-draw/{id}
lichess_cancel_draw_offer ANY /cancel-draw-offer/{id}
lichess_accept_draw_offer ANY /accept-draw-offer/{id}
lichess_decline_draw_offer ANY /decline-draw-offer/{id}
lichess_moretime ANY /moretime/{id}
lichess_status ANY /status
lichess_ping ANY /ping
lichess_sync ANY /sync/{id}/{color}/{version}/{playerFullId}