Skip to content

Instantly share code, notes, and snippets.

@twistedpair
Last active July 31, 2016 18:05
Show Gist options
  • Save twistedpair/58414ee3237544eaf54a787a59f656c6 to your computer and use it in GitHub Desktop.
Save twistedpair/58414ee3237544eaf54a787a59f656c6 to your computer and use it in GitHub Desktop.
Simple performance benchmark for block post: https://lustforge.com/2016/05/08/modulo-operator-performance-impact/
/**
Simple benchmark of different ways to do modulo
- Numbers collected on a 4Ghz i7-4790K, 8 core AMD, 32GB PC3 19200 ram, SSD
- Scala 2.11.8
- Java 1.8.0_91
# scalac mod_perf.scala && scala ModPerf
**/
object ModPerf extends App {
final val N = 1000000
final val RandInts:Array[Int] = Array.fill(N){scala.util.Random.nextInt(1000)+2000000000} // big values, more expensive
final val RandDoubles:Array[Double] = Array.fill(N){scala.util.Random.nextDouble * 2000000000}
// This isn't very functional. Not passing functions, so we're not measuring "f.apply()" overhead
// Not storing output, as again I don't want to measure that aspect
// Not using mapping of collections, fors or iterators - don't want to measure their overhead
// Similar proportion of time taken when using RandInts(_ % b), for comprehension, etc
def timedOldDouble(n:Int):Long = {
val start = System.nanoTime()
val d:Double = 61d
val b:Double = 8d
var i =0 // cheaper than using a for iterator, comprension, or collection mapping
while (i < n) {
RandDoubles(i) % b
i+=1
}
val deltaNanos = System.nanoTime() - start
deltaNanos
}
def timedOldInt(n:Int):Long = {
val start = System.nanoTime()
val d:Int = 61
val b:Int = 8
var i =0
while (i < n) {
RandInts(i) % b
i+=1
}
val deltaNanos = System.nanoTime() - start
deltaNanos
}
def timedPow2(n:Int):Long = {
val start = System.nanoTime()
val d:Int = 61
val b:Int = 8-1
var i =0
while (i < n) {
RandInts(i) & b
i+=1
}
val deltaNanos = System.nanoTime() - start
deltaNanos
}
// warmpup pass
timedOldDouble(N)
timedOldInt(N)
timedPow2(N)
// actual run
val ns1 = timedOldDouble(N)
val ns2 = timedOldInt(N)
val ns3 = timedPow2(N)
// Basic stats
val mean1 = ns1.toDouble/N.toDouble
val mean2 = ns2.toDouble/N.toDouble
val mean3 = ns3.toDouble/N.toDouble
println (s"FModDoubles ran in $ns1 ns, average: ${mean1} ns")
println (s"IRemIntegers ran in $ns2 ns, average: ${mean2} ns")
println (s"ModPow2 ran in $ns3 ns, average: ${mean3} ns")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment