an old man and a park bench
I sat down next to an old man on a park bench today. He said to me:
Are you just going to sit there?
So I said:
Why do you ask?
To which he replied:
I’m an old man. These days, what I enjoy most is to sit here and watch others go about their business, over and over, and over again.
I went on my way. I came back to the bench the next day and the old man and the bench was gone.
So I build myself a new bench to sit and watch on my own, occasionally glancing at my watch.
To Build a Bench
I bought a hammer and a few planks of wood and this is what I made:
package park
trait Bench {
object Timing {
case class Time(cpu: Long, user: Long, system: Long, real: Long) {
val tuple = (cpu, user, system, real)
def - (t: Time) = Time(
cpu - t.cpu, user - t.user, system - t.system, real - t.real
)
def + (t: Time) = Time(
cpu + t.cpu, user + t.user, system + t.system, real + t.real
)
}
def cpu = get(bean getCurrentThreadCpuTime)
def user = get(bean getCurrentThreadUserTime)
def real = System.nanoTime
def system = cpu - user
def now = Time(cpu, user, system, real)
val empty = Time(0l, 0l, 0l, 0l)
def get(fn: => Long) = if(bean isCurrentThreadCpuTimeSupported) fn else 0l
private val bean = java.lang.management.ManagementFactory.getThreadMXBean
}
def watch(n: Int, o: Int) = {
headers
for(i <- Stream.range(0, o)) collect(n)
}
def collect(times: Int) = tell(subject, (Timing.empty /: observe(times))(_+_))
def subject = getClass getName
def observe(n: Int) = for(i <- Stream.range(0, n)) yield time { run }
def time(block: => Any) = {
val before = Timing.now
block
val after = Timing.now
after - before
}
def headers = println(
(" "*subject.size)+"\t\tcpu\t\tuser\t\tsystem\t\treal"
)
def tell(subject: String, time: Timing.Time) = {
def sec(n: Long) = n / 1000000000.0
val (cpu, user, system, real) = time.tuple
println(
"%s\t\t%f\t%f\t%f\t%f" format(
subject, sec(cpu), sec(user), sec(system), sec(real)
)
)
}
/** where unicorns do run wild */
def run
}
Bird Watching and other Leisurely Observations
I stepped back to have a look at this new park bench.
From here, I can watch flocks of inline invokations fly by, one or more times.
scala> val b = new Bench { def run = 1+1; override def subject = "plus" }
scala> b watch(2, 2)
I jotted down what I saw.
cpu user system real
plus 0.000067 0.000027 0.000021 0.000046
plus 0.000054 0.000028 0.000021 0.000108
Under a tree, I can watch those pass the time by reading favored books.
object BookShelfBench extends BookShelf with park.Bench {
def run = read(Book("a tale of two cities"))
override def subject = "reading"
}
BookShelfBench watch(10, 1)
To be honest, I really didn’t have time to watch them finish this book.
cpu user system real
reading a really long time...
This was just a quick and silly re-composition of an idea I had while glancing at scala.testing.Benchmark. This idea may become a real project as some point on the githubs. For now it was just flash coding. Isn’t composition fun?