Skip to content

Instantly share code, notes, and snippets.

@ymnk
Created March 3, 2011 08:58
Show Gist options
  • Save ymnk/852527 to your computer and use it in GitHub Desktop.
Save ymnk/852527 to your computer and use it in GitHub Desktop.
Sample code for understanding
'Scala Performance Considerations'
https://docs.google.com/present/view?id=0AS8emH3-FLt3ZGRtbWJyOGdfMTFmcDZkcTk2cw&hl=en
object ForLoop extends Test {
final val times = 10
def main(arg: Array[String]) = {
test1
test2
}
def test1 = {
benchmark("for loop", times){
var s = 0
for {i <- 1 to 2000
j <- 1 to 2000;
k <- 1 to 2000}
s += 1
}
}
def test2 = {
benchmark("while loop", times){
var s = 0
var i = 1; var j = 1; var k = 1
while (i <= 2000) {
j = 1
while (j <= 2000) {
k = 1
while (k <= 2000) {
k += 1
}
j += 1
}
i += 1
}
}
}
}
// This code is from https://lampsvn.epfl.ch/trac/scala/ticket/1338
object MatMul {
def matMulUsingIterators (
a : Array[Array[Double]],
b : Array[Array[Double]],
c : Array[Array[Double]]) : Unit = {
val b_j = new Array[Double](b.length)
for (j <- 0 until b(0).length) {
for (k <- 0 until b.length) {
b_j(k) = b(k)(j)
}
for (i <- 0 until a.length) {
val c_i = c(i)
val a_i = a(i)
var s = 0.0d;
for (k <- 0 until b.length) {
s += a_i(k) * b_j(k)
}
c_i(j) = s
}
}
}
def matMulUsingRanges (
a : Array[Array[Double]],
b : Array[Array[Double]],
c : Array[Array[Double]]) : Unit = {
val jRange = 0 until b(0).length // p
val kRange = 0 until b.length // n
val iRange = 0 until a.length // m
val b_j = new Array[Double](b.length)
for (j <- jRange) {
for (k <- kRange) {
b_j(k) = b(k)(j)
}
for (i <- iRange) {
val c_i = c(i)
val a_i = a(i)
var s = 0.0d;
for (k <- kRange) {
s += a_i(k) * b_j(k)
}
c_i(j) = s
}
}
}
def matMulUsingLimits (
a : Array[Array[Double]],
b : Array[Array[Double]],
c : Array[Array[Double]]) : Unit = {
val b_j = new Array[Double](b.length)
val m = a.length
val p = b(0).length
val n = b.length
for (j <- 0 until p) {
for (k <- 0 until n) {
b_j(k) = b(k)(j)
}
for (i <- 0 until m) {
val c_i = c(i)
val a_i = a(i)
var s = 0.0d;
for (k <- 0 until n) {
s += a_i(k) * b_j(k)
}
c_i(j) = s
}
}
}
def matMulUsingWhileLoop (
a : Array[Array[Double]],
b : Array[Array[Double]],
c : Array[Array[Double]]) : Unit = {
val m = a.length
val p = b(0).length
val n = b.length
val b_j = new Array[Double](b.length)
var i = 0; var j = 0; var k = 0
while (j < p) {
k = 0
while (k < n) {
b_j(k) = b(k)(j)
k += 1
}
i = 0
while (i < m) {
val c_i = c(i)
val a_i = a(i)
var s = 0.0d;
k = 0
while (k < n) {
s += a_i(k) * b_j(k)
k += 1
}
c_i(j) = s
i += 1
}
j += 1
}
}
def time[R](block: => R) : (Long, R) = {
val start = System.nanoTime()
val result : R = block
val time = System.nanoTime() - start
(time, result)
}
val format = new java.text.DecimalFormat("0,000'ns'");
def report[R](label: String, result: (Long, R)) = {
println(label + " " + format.format(result._1))
}
private val FACTOR = 5
private val M = 80
private val N = 70
private val P = 60
def main(args : Array[String]) = {
for (trial <- 3 until 0 by -1) {
val factor = (if (System.getProperty("factor") != null)
Integer.parseInt(System.getProperty("factor"))
else
FACTOR)
val multiplier = if (trial == 1) factor else 1;
val m = M * multiplier
val n = N * multiplier
val p = P * multiplier
val a = new Array[Array[Double]](m,n)
val b = new Array[Array[Double]](n,p)
val c = new Array[Array[Double]](m,p)
println("\nMultiply c[" + m + "," + p + "] = a[" + m + "," + n + "] times b[" + n + "," + p + "]\n");
val whileTime = time(matMulUsingWhileLoop(a,b,c))
val iterTime = time(matMulUsingIterators(a,b,c))
report("Iterators ", iterTime)
report("Limits ", time(matMulUsingLimits(a,b,c)))
report("Ranges ", time(matMulUsingRanges(a,b,c)))
report("While Loop ", whileTime)
println("MatMul by Iterators is " + iterTime._1 / whileTime._1 + " times as slow as with while loops.")
}
}
}
// JAVA_OPTS='-Xmx256M -Xms32M -server -XX:+DoEscapeAnalysis'
object StructuralTypes extends Test {
final val times = 10
def main(arg: Array[String]) = {
test1
test2
}
def test1 = {
implicit def toInOperand[A](a: A) = new {
def in(seq: Seq[A]) = seq.contains(a)
}
benchmark("using structural types", times, 100){
var a: Long = 0
for (i <- 1 to 10000) {
if (i in List(7,77,777)) a += 1
if (i.toString in
List("8","88","888")) a += 1
if ((i * 2) in
List (6, 66, 666)) a += 1
}
}
}
def test2 = {
class InOperand[A](a: A) {
def in(seq: Seq[A]) = seq.contains(a)
}
implicit def toInOperand[A](a: A) = new InOperand(a)
benchmark("without structural types", times, 100){
var a: Long = 0
for (i <- 1 to 10000) {
if (i in List(7,77,777)) a += 1
if (i.toString in
List("8","88","888")) a += 1
if ((i * 2) in
List (6, 66, 666)) a += 1
}
}
}
}
// JAVA_OPTS='-Xmx256M -Xms32M -server'
import scala.testing.Benchmark
trait Test {
def benchmark(name: String, times: Int, mult: Int = 1)(f: =>Any) = new Benchmark{
multiplier = mult
def run() = f
}.runBenchmark(times) match {
case l =>
println(name+" "+(l.sum-l.max-l.min).toDouble/(l.size-2))
}
}
object TraitAbstClass extends Test {
final val times = 10
def main(arg: Array[String]) = {
test1
test2
}
def test1 = {
trait Foo {
def t: Unit = ()
}
val foo = new Foo{}
benchmark("invokeinterface", times, 1000){
foo.t
}
}
def test2 = {
abstract class Bar {
def a: Unit = ()
}
val bar = new Bar{}
benchmark("invokevirtual", times, 1000){
bar.a
}
}
}
object TypeSpecialize extends Test {
final val times = 10
def main(arg: Array[String]) = {
test1
test2
}
def test1 = {
benchmark("without specialization", times){
val a = new My1[Int]
for (i <- 1 to 1000000) a.iden(i)
}
}
def test2 = {
benchmark("with specialization", times){
val a = new My2[Int]
for (i <- 1 to 1000000) a.iden(i)
}
}
class My2[@specialized(Int) A] {
def iden(x: A): A = x
}
class My1[A] {
def iden(x: A): A = x
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment