fork(5) download
  1.  
  2. // scala 合算実験 <http://w...content-available-to-author-only...e.jp/asahi/hishidama/home/tech/scala/sample/sum.html>
  3. // に参加してみた (by @akihiro4chawon)
  4.  
  5. // ・基本的に @hishidama さんのルーチンを流用
  6. // ・再帰関数が、Array/Vectorに不利なルーチン(毎回 tail をとっている)になっているのを修正(添字による)
  7. // なお、このパフォーマンスについては、IndexedSeq と LinearSeq の違いについて踏まえた上で文書化されている
  8. // ・最速ルーチンを提案してみた (def sumByFastestWhile)
  9. // ただし、これが最速であることは規格としては保証されない。scala/JVM実装依存
  10.  
  11. object Main {
  12. case class Sample(
  13. val value1: Int,
  14. val value2: Int,
  15. val value3: Long
  16. )
  17. val list = List.range(1, 10000+1).map(n => Sample(1,n,n*5))
  18. val vector = Range(1, 10000+1).map(n => Sample(1,n,n*5))
  19. val array = Array.range(1, 10000+1).map(n => Sample(1,n,n*5))
  20.  
  21. def benchmark(times: Int, mult: Int = 1)(f: =>Any) =
  22. new scala.testing.Benchmark{ multiplier = mult; def run() = f }.runBenchmark(times)
  23. implicit def benchmark2report(list:List[Long]) =
  24. new { def report() = { println(list); println((list.sum - list.max - list.min).toDouble / (list.size-2)) }}
  25.  
  26. def sumByWhile(list: Seq[Sample]) = {
  27. var sum1 = 0
  28. var sum2 = 0
  29. var sum3 = 0L
  30. val i = list.iterator
  31. while(i.hasNext) {
  32. val c = i.next
  33. sum1 += c.value1
  34. sum2 += c.value2
  35. sum3 += c.value3
  36. }
  37. (sum1, sum2, sum3)
  38. }
  39.  
  40. def sumByFastestWhile(list: Array[Sample]): (Int, Int, Long) = {
  41. var sum1, sum2 = 0
  42. var sum3: Long = 0L
  43. var idx = 0
  44. try {
  45. while (true) {
  46. val c = list(idx)
  47. sum1 += c.value1
  48. sum2 += c.value2
  49. sum3 += c.value3
  50. idx += 1
  51. }
  52. } catch {
  53. case e: java.lang.ArrayIndexOutOfBoundsException => // loop finished!
  54. return (sum1, sum2, sum3)
  55. }
  56. assert(false) // How'd they finished the loop?
  57. }
  58.  
  59. def sumByRec(list: Seq[Sample]) = {
  60. def f(list:Seq[Sample], sum1:Int = 0, sum2:Int = 0, sum3:Long = 0L): (Int,Int,Long) = {
  61. if(list.isEmpty) {
  62. (sum1, sum2, sum3)
  63. } else {
  64. val c = list.head
  65. f(list.tail, sum1+c.value1, sum2+c.value2, sum3+c.value3)
  66. }
  67. }
  68. f(list)
  69. }
  70.  
  71. def sumByRec2(list: Seq[Sample]) = {
  72. def f(idx: Int, sum1: Int = 0, sum2: Int = 0, sum3: Long = 0L): (Int, Int, Long) = {
  73. if (list.size == idx)
  74. (sum1, sum2, sum3)
  75. else {
  76. val c = list(idx)
  77. f(idx + 1, sum1 + c.value1, sum2 + c.value2, sum3 + c.value3)
  78. }
  79. }
  80. f(0)
  81. }
  82.  
  83. def main(args: Array[String]) {
  84. println(" --- sum by while --- ")
  85. println("list")
  86. benchmark(10, 100){ sumByWhile(list) }.report
  87. println("vector")
  88. benchmark(10, 100){ sumByWhile(vector) }.report
  89. println("array")
  90. benchmark(10, 100){ sumByWhile(array) }.report
  91.  
  92. println(" --- sum by recursion --- ")
  93. benchmark(10, 100){ sumByRec(list) }.report
  94. //benchmark(10, 100){ sumByRec(vector) }.report // 論外
  95. //benchmark(10, 100){ sumByRec(array) }.report // 論外
  96.  
  97. //benchmark(10, 100){ sumByRec2(list) }.report // 論外
  98. benchmark(10, 100){ sumByRec2(vector) }.report
  99. benchmark(10, 100){ sumByRec2(array) }.report
  100.  
  101. println(" --- 最速の例外脱出法 --- ")
  102. benchmark(10, 100){ sumByFastestWhile(array) }.report
  103.  
  104. }
  105.  
  106. }
Success #stdin #stdout 4.84s 212864KB
stdin
Standard input is empty
stdout
 --- sum by while --- 
list
List(73, 66, 64, 64, 61, 61, 61, 61, 61, 61)
62.375
vector
List(37, 31, 30, 30, 31, 31, 31, 30, 31, 31)
30.75
array
List(38, 34, 33, 34, 34, 34, 33, 34, 34, 34)
33.875
 --- sum by recursion --- 
List(47, 40, 39, 39, 40, 40, 40, 39, 40, 40)
39.75
List(78, 68, 67, 68, 67, 68, 68, 67, 67, 67)
67.5
List(62, 67, 61, 69, 70, 68, 63, 60, 61, 62)
64.125
 --- 最速の例外脱出法 --- 
List(11, 7, 8, 8, 8, 7, 7, 8, 8, 8)
7.75