我已经翻译了命令式行计数代码(请参见
这是我的完整测试代码:
linesGt1
),从Functional Programming in Scala第15章的开头到使用scalaz-stream(请参见linesGt2
)的解决方案。然而,linesGt2
的性能并不是很好。命令式代码比我的scalaz-stream解决方案快约30倍。所以我想我做错了什么基本的事情。如何提高scalaz-stream代码的性能?这是我的完整测试代码:
import scalaz.concurrent.Task
import scalaz.stream._
object Test06 {
val minLines = 400000
def linesGt1(filename: String): Boolean = {
val src = scala.io.Source.fromFile(filename)
try {
var count = 0
val lines: Iterator[String] = src.getLines
while (count <= minLines && lines.hasNext) {
lines.next
count += 1
}
count > minLines
}
finally src.close
}
def linesGt2(filename: String): Boolean =
scalaz.stream.io.linesR(filename)
.drop(minLines)
.once
.as(true)
.runLastOr(false)
.run
def time[R](block: => R): R = {
val t0 = System.nanoTime()
val result = block
val t1 = System.nanoTime()
println("Elapsed time: " + (t1 - t0) / 1e9 + "s")
result
}
time(linesGt1("/home/frank/test.txt")) //> Elapsed time: 0.153122057s
//| res0: Boolean = true
time(linesGt2("/home/frank/test.txt")) //> Elapsed time: 4.738644606s
//| res1: Boolean = true
}
scalaz-stream
的专家,但这对我来说看起来很合理(尽管我可能会使用类似.once.runLast.run.nonEmpty
的东西)。使用drop
逐行步进需要很多开销,我猜这就是你在这里看到的。 - Travis Brown