The problem -----------
I’m currently in the process of letting extensions to be written for the NetBeans Gradle integration. While doing so, I have realized that there is a very serious performance issue to be solved.
In NetBeans you may load all the projects of a multi-project build separately. This improves performance when dealing with large multi-project builds if you are not actually editing all the projects (less classpath to index). As of now, if you were loading an IdeaProject, all Gradle projects were actually loaded (by the Tooling API). Therefore, I could simply parse all of them and cache them, so subsequent project loads of the same multi-project build were close to a no-op.
However, Gradle 1.6 introduced the possibility of loading 3rd party models. This is nice but as of the current version of the Tooling API, this brings a major performance issue (given that I want to exploit the new feature of Gradle). Namely, it is likely that users are keeping open multiple projects of the same multi-project build. Assume that I request the Tooling API for models specifying one of those projects. It is likely that evaluating a project will cause the evaluation of multiple other Gradle projects (as of now, every project is evaluated). Given that multiple projects are evaluated it is a considerable waste not to have models for other evaluated projects as well. That is, if I attempt to load the next project, I cannot refer to my cache because that project has not yet been loaded and I cannot deduce what will happen if I request the Tooling API. This will eventually lead me to many unnecessary project evaluation, which will have a huge performance impact.
Finding a solution for this problem is extremly important for making use of 3rd party models (or anything beyond models currently available in Gradle). That is, without a solution I cannot use the new feature without a huge performance hit (even for projects not using 3rd party models).
Example -------
Assume that someone writes a Jacoco model. Also assume that there is a NetBeans Gradle extension which is aware of this model. Since I have to faithfully serve models for extensions, I will have no chance but to load each project separately even though projects were evaluated. Notice that having this Gradle extension installed will slow down loading of plain old J2SE projects even if they do not really use the extension mentioned previously. This is simply unacceptable.
A possible solution -------------------
Unlike ‘ProjectConnection’, provide a short lived connection to the daemon which does not reevaluate the project if a new model is requested. Also, I expect this connection to be able to tell if there are projects already evaluated. For example:
DaemonConnection connection = ...;
EvaluatedProject project = connection.evaluateProject(projectDir);
List<MyModel> models = new LinkedList<>();
models.add(project.getModel(MyModel.class));
for (EvaluatedProject otherProject: project.getOtherEvaluatedProjects()) {
models.add(otherProject.getModel(MyModel.class));
}
I hope that the example code above describes the proposed solution clearly enough. Notice that this also solves my previously reported issue as well.
Thank you for your attention