summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-03-29 13:15:30 +0100
committerJason Zaugg <jzaugg@gmail.com>2013-03-29 13:50:13 +0100
commit246eceb830ec1efb43a9b02424637c1e6b6a978b (patch)
tree5ad364b7c1f469169a1f25447aacf4ecb98a1eed
parent0cb632440e07ce370a3b97f81a81ee920eadb282 (diff)
downloadscala-246eceb830ec1efb43a9b02424637c1e6b6a978b.tar.gz
scala-246eceb830ec1efb43a9b02424637c1e6b6a978b.tar.bz2
scala-246eceb830ec1efb43a9b02424637c1e6b6a978b.zip
Optimization: avoid isDirectory call in DirectoryClassPath traversal
If we just established that the given path is a File or a Directory, we don't need to go straight back to disk to re-check. Background: When profiling an application that was using the interpreter to compile a script, a lot of time was reported in exists / isDirectory / isFile. For the record, I happened to be profiling on Windows. Turns out some of these calls are redundant, this commit and the subsequent eliminate two sources thereof. Here's an example of how it helps: Taking a Hello, Akka! application, and compiling it with the compiler and library on a directory classpath (ie, using build/quick): class HelloActor extends Actor { def receive = { case "hello" => println("hello back at you") case _ => println("huh?") } } object Main extends App { val system = ActorSystem("HelloSystem") // default Actor constructor val helloActor = system.actorOf(Props[HelloActor], name = "helloactor") helloActor ! "hello" helloActor ! "buenos dias" } % qbin/scalac -Ystatistics -classpath ~/.ivy2/cache/com.typesafe.akka/akka-actor_2.10/jars/akka-actor_2.10-2.1.1.jar:/Users/jason/.ivy2/cache/com.typesafe/config/bundles/config-1.0.0.jar sandbox/test.scala 2>&1 | grep File Before ---------------------------------- File.isFile calls : 7620 File.isDirectory calls : 8348 File.exists calls : 5770 After ---------------------------------- File.isFile calls : 7620 File.isDirectory calls : 2319 File.exists calls : 5770
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index aa4128f1a7..7f9b81e1ec 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -281,11 +281,24 @@ class DirectoryClassPath(val dir: AbstractFile, val context: ClassPathContext[Ab
private def traverse() = {
val classBuf = immutable.Vector.newBuilder[ClassRep]
val packageBuf = immutable.Vector.newBuilder[DirectoryClassPath]
- dir foreach { f =>
- if (!f.isDirectory && validClassFile(f.name))
- classBuf += ClassRep(Some(f), None)
- else if (f.isDirectory && validPackage(f.name))
- packageBuf += new DirectoryClassPath(f, context)
+ dir foreach {
+ f =>
+ // Optimization: We assume the file was not changed since `dir` called
+ // `Path.apply` and categorized existent files as `Directory`
+ // or `File`.
+ val isDirectory = f match {
+ case pf: io.PlainFile => pf.givenPath match {
+ case _: io.Directory => true
+ case _: io.File => false
+ case _ => f.isDirectory
+ }
+ case _ =>
+ f.isDirectory
+ }
+ if (!isDirectory && validClassFile(f.name))
+ classBuf += ClassRep(Some(f), None)
+ else if (isDirectory && validPackage(f.name))
+ packageBuf += new DirectoryClassPath(f, context)
}
(packageBuf.result(), classBuf.result())
}