Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine when Play! 2 must recompile all files?

When I edit a scala file in my Play 2 app, sometimes only a few files are recompiled, but often the entire codebase must be recompiled:

[info] Compiling 1 Scala source to /home/michael/code/superglot/target/scala-2.10/classes...
[success] Compiled in 1s

versus

[info] Compiling 2 Scala sources to /home/michael/code/superglot/target/scala-2.10/classes...
[info] Compiling 52 Scala sources and 1 Java source to /home/michael/code/superglot/target/scala-2.10/classes...
[success] Compiled in 13s

However I see no discernible pattern for when a full recompile is necessary. If I add somewhitespace to a model or controller class it may only compile that file, but doing the same to a comparable file will trigger a recompile.

I would love to have as many of my reloads be closer to 1s, because currently I'm waiting for a full recompile more often than not. I'd gladly refactor my code to make the areas I'm working on faster to reload, but I don't know what I could even do to achieve that. Are frequent recompiles normal for a typical Play 2 app, or is there something anomalous about mine?

like image 331
maackle Avatar asked May 10 '13 20:05

maackle


2 Answers

In general, if you change the "source API" of a file, dependencies of that file are recompiled. The source API consists of the signatures of non-private methods and types. So, if you have a file that everything depends on, changes to signatures in that file may cause a lot of recompilation. Also, when an ancestor's API changes, all descendents must be recompiled.

You can get some additional information from last compile, such as what triggered other files to be recompiled. (In a multi-module build, last <project-name>/compile) You can

If adding insignificant whitespace causes other files to be recompiled, it is always a bug, often in scalac itself. An example of such a bug is SI-7361 (not that it is useful to anyone besides compiler developers!) that was worked around in sbt here. For these to be fixed, we need a reproducible test case. (Given the effort often involved in that, you might wait for 0.12.4 or 0.13.0 to see if those fix your problem.)

0.13.0 has some improvements that will hopefully reduce what gets invalidated when APIs change.

like image 52
Mark Harrah Avatar answered Nov 11 '22 06:11

Mark Harrah


I think you are going for the slightly wrong approach here. As there is no way to successfully determine which changes will cause the full re-compilation, that path leads nowhere.

For learning purposes perhaps it is helpful to be aware of the compiler's internals to a better extent, but from a productivity perspective there is a much better choice available, and that is jRebel, who have been giving out free Scala licenses for years.

JRebel

From here, you can get a free Scala license within minutes. Then go ahead and add this to the sbt config. It has to go straight into the sbt file.

Linux/Mac

java -noverify -javaagent:/opt/zt/jrebel/jrebel.jar \
 -Xmx1024M -Xss2M -XX:MaxPermSize=512m -XX:+CMSClassUnloadingEnabled -jar \
 `dirname $0`/sbt-launch-0.12.jar "$@"

Windows

set SCRIPT_DIR=%~dp0
java -noverify -javaagent:c:/opt/zt/jrebel/jrebel.jar \
 -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx1024M -Xss2M \
 -jar "%SCRIPT_DIR%\sbt-launch-0.12.jar" %*

At this stage, if you've done everything right, when you re-start the SBT console you will see that the jRebel Agent has been initiated and you will benefit from the real-time redeployment of your changes. When you Save in your IDE, JRebel will reload only the changes you've made.

like image 26
flavian Avatar answered Nov 11 '22 05:11

flavian