Skip to content

Instantly share code, notes, and snippets.

@nakhli
Created July 14, 2011 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nakhli/1083157 to your computer and use it in GitHub Desktop.
Save nakhli/1083157 to your computer and use it in GitHub Desktop.
Benchmarking two Scala atoi implementations: foldLeft vs random access
// <copyright file="BenchmarkAtoi.scala" company="http://www.javageneration.com">
// Copyright (c) Chaker Nakhli 2011
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
// applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
// </copyright>
// <author>Chaker Nakhli</author>
// <email>Chaker.Nakhli@javageneration.com</email>
// <date>2011/07/14</date>
package com.javageneration
object Atoi {
def withRandomAccess(str: String, baze: Int): Int = {
def process(acc: Int, place: Int, str: String, index: Int): Int =
if (index >= 0) process(acc + value(str.charAt(index)) * place, place * baze, str, index-1) else acc
process(0, 1, str, str.length - 1)
}
def withFoldLeft(str: String, base: Int): Int = (0/:str) (_ * base + value(_))
def value(c: Char): Int = {
if (c == '+') 62
else if (c == '/') 63
else if (c < '0') throw new IndexOutOfBoundsException("c");
else if (c < ':') c - '0';
else if (c < 'A') throw new IndexOutOfBoundsException("c");
else if (c < '[') c - 'A' + 10;
else if (c < 'a') throw new IndexOutOfBoundsException("c");
else if (c < '{') c - 'a' + 36;
else throw new IndexOutOfBoundsException("c");
}
def symbol(i: Int): Char = {
if (i < 0) throw new IndexOutOfBoundsException("i")
else if (i < 10) ('0' + i).toChar
else if (i < 36) ('A' + i - 10).toChar
else if (i < 62) ('a' + i - 36).toChar
else if (i == 62) '+'
else if (i == 63) '/'
else throw new IndexOutOfBoundsException("i");
}
}
object Main {
def main(args: Array[String]): Unit = {
val MAX = 100000000
benchmark(MAX, "1111111111111111111111111111111", 2)
benchmark(MAX, "2147483647", 10)
benchmark(MAX, "1/////", 64)
benchmark(MAX, "0", 10)
}
def benchmark(max: Int, str: String, baze: Int): Unit = {
printf("** Input: Base=%d Str=\"%s\" - Atoi.withRandomAccess Output: %d - Atoi.withFoldLeft Output: %d **\n",
baze, str, Atoi.withRandomAccess(str, baze), Atoi.withFoldLeft(str, baze))
perf(max, " Atoi.withRandomAccess :") { Atoi.withRandomAccess(str, baze) }
perf(max, " Atoi.withFoldLeft :") { Atoi.withFoldLeft(str, baze) }
println
}
def perf(max: Int, label: String)(action: => Unit): Unit = {
var startedAt = System.currentTimeMillis()
for (i <- 0 until max) action
printf("%s %.0f ns\n", label, (System.currentTimeMillis() - startedAt) * 1000000.0 / max)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment