diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-03-29 13:15:30 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-03-29 13:50:13 +0100 |
commit | 246eceb830ec1efb43a9b02424637c1e6b6a978b (patch) | |
tree | 5ad364b7c1f469169a1f25447aacf4ecb98a1eed /src/compiler/scala/tools/nsc/util/ClassPath.scala | |
parent | 0cb632440e07ce370a3b97f81a81ee920eadb282 (diff) | |
download | scala-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
Diffstat (limited to 'src/compiler/scala/tools/nsc/util/ClassPath.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/util/ClassPath.scala | 23 |
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()) } |