All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.concurrent.stm.ccstm.Stats.scala Maven / Gradle / Ivy

/* scala-stm - (c) 2009-2011, Stanford University, PPL */

package scala.concurrent.stm.ccstm

import collection.mutable.ArrayBuffer

private[ccstm] object Stats {

  val Enabled = "yYtT1".indexOf((System.getProperty("ccstm.stats", "") + "0").charAt(0)) >= 0

  class LazyCounterMap[A] {
    import scala.collection.JavaConversions._

    private val _counters = new java.util.concurrent.ConcurrentHashMap[A, Counter]

    def += (k: A) {
      var v = _counters.get(k)
      if (v == null) {
        _counters.putIfAbsent(k, new Counter)
        v = _counters.get(k)
      }
      v += 1
    }

    def toStr(k: A): String = k.toString

    def contents: Seq[(String, Long)] = {
      val aa = _counters.entrySet.toSeq map { e => (toStr(e.getKey) -> e.getValue.apply()) }
      aa sortBy { -_._2 }
    }
  }

  class Histo(numBuckets: Int) {
    private val _sum = new Counter
    private val _buckets = Array.tabulate(numBuckets) { _ => new Counter }

    def += (value: Int) {
      if (value != 0) {
        _sum += value
        _buckets(bucketFor(value)) += 1
      }
    }

    protected def bucketFor(value: Int): Int = {
      if (value < 0 || value >= _buckets.length)
        _buckets.length - 1
      else
        value
    }

    def contents: Seq[Long] = {
      val snap = _buckets map { _.apply() }
      snap.take(1 + snap.lastIndexWhere { _ != 0L })
    }

    override def toString = {
      val s = _sum()
      val c = contents
      val count = c.foldLeft(0L)( _ + _ )
      val avg = if (count == 0) 0.0 else s * 1.0 / count
      "sum= %-10d count= %-8d avg= %-5.1f [%s]".format(s, count, avg, c.mkString(" "))
    }
  }

  class ExponentialHisto extends Histo(32) {
    override protected def bucketFor(value: Int): Int = {
      var v = value >>> 1
      var i = 0
      while (v != 0) {
        v >>>= 1
        i += 1
      }
      i
    }
  }

  class Level(isTop: Boolean) {
    val commits = new Counter
    val alternatives = new Histo(10)
    val retrySet = if (isTop) new ExponentialHisto else null
    val retryWaitElapsed = if (isTop) new ExponentialHisto else null
    val explicitRetries = new Counter
    val optimisticRetries = new LazyCounterMap[Symbol]
    val failures = new LazyCounterMap[Class[_]] { override def toStr(k: Class[_]) = k.getSimpleName }
    val blockingAcquires = new Counter
    val commitReadSet = if (isTop) new ExponentialHisto else null
    val commitBargeSet = if (isTop) new ExponentialHisto else null
    val commitWriteSet = if (isTop) new ExponentialHisto else null
    val rollbackReadSet = new ExponentialHisto
    val rollbackBargeSet = new ExponentialHisto
    val rollbackWriteSet = new ExponentialHisto

    def contents: Seq[String] = {
      val buf = new ArrayBuffer[String]
      for (f <- getClass.getDeclaredFields) {
        val name = f.getName
        val value = getClass.getDeclaredMethod(name).invoke(this)
        value match {
          case null =>
          case c: Counter => buf += "%17s= %d".format(name, c())
          case m: LazyCounterMap[_] => {
            for ((k, v) <- m.contents)
              buf += "%17s: %7d %s".format(name, v, k)
          }
          case h: Histo => buf += "%17s: %s".format(name, h)
        }
      }
      buf.result
    }

    def mkString(prefix: String): String = {
      prefix + ("-" * 64) + "\n" + contents.map( prefix + _ ).mkString("\n")
    }
  }

  val top = if (Enabled) new Level(true) else null
  val nested = if (Enabled) new Level(false) else null
  registerShutdownHook()

  private def registerShutdownHook() {
    if (top != null)
      Runtime.getRuntime.addShutdownHook(new Thread("shutdown stats printer") {
        override def run() { println(Stats) }
      })
  }

  override def toString() = {
    top.mkString("CCSTM: top: ") + "\n" + nested.mkString("CCSTM: nested: ")
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy