On 03/02/2013, at 9:20 PM, Luke Daley wrote:

> 
> 
> On 03/02/2013, at 10:02, Hans Dockter <[email protected]> wrote:
> 
>> 
>> 
>> On Sat, Feb 2, 2013 at 11:50 PM, Adam Murdoch <[email protected]> 
>> wrote:
>> Hi,
>> 
>> Something I'd like to try to achieve as part of the work to introduce 
>> multiple outputs for JVM based projects, is to create fewer task instances 
>> at configuration time. There are 2 main parts to this:
>> 
>> 1. Don't create tasks that will never be required. For example, if there is 
>> no src/main/resources directory, and nothing generates it, then don't create 
>> a processResources task.
>> 2. Don't create tasks that are not required for the current build. For 
>> example, if I'm generating the javadoc, don't create the test task or any of 
>> its dependencies.
>> 
>> Ignore for the moment how we might do this. Let's just say its possible to 
>> infer both #1 and #2.
>> 
>> Which would be awesome. But doesn't it leave the door open for certain 
>> undetectable(?) configuration time dependencies? I would say if we are able 
>> to reliably solve that problem, reliable parallel task execution isn't far 
>> away either (if we want to go for it). 
>> 
>> Let's also say that if such as task is directly referenced in the build 
>> logic, then it's "required". For example, if I execute 
>> `myTask.dependsOn(processResources)` in my build script, then 
>> processResources is required and must be created. Possibly also for the 
>> command-line, so that if I run `gradle processResources`, then it is 
>> required.
>> 
>> The question is whether we consider it backwards compatible or not that we 
>> don't create certain tasks that used to always be created.
>> 
>> At first glance, it looks not too bad. The tasks don't do anything and 
>> nothing references them from code, so it's fine to leave them out. There are 
>> a few important benefits to doing this:
>> 
>> - There's less work to do at configuration time.
> 
> This doesn't seem certain to me. The calculation on whether something is 
> really needed may not be "free".

That is true. However, we do know that creating and configuring tasks is 
relatively expensive. And we know that inferring whether there is, say, test 
source, can be cheap (do any of the test source directories exist?).

We would do the inference only when something is required by a build. So, we'd 
only infer whether we need a task to compile test classes only if we're running 
the tests. So, you're replacing the cost of configuring every possibility in 
every build with the cost of inferring only what is required for the build.

> 
> Depends on how efficient the inference is.
> 
>> - There's less heap required to maintain the model through the whole build.
>> - We wouldn't log the execution of tasks that don't do anything. For 
>> example, if there is no test source, you wouldn't see 'testClasses', 
>> 'compileTestJava', 'processTestResources' etc.
>> 
>> Which is a strong indicator that we are doing something right here.
>>  
>> - It pushes the decoupling of 'what' and 'how', which means the 'how' can 
>> vary across different executions of the same build. For example, when 
>> generated source must be downloaded when building on one platform but can be 
>> generated when building on some other platform. Or when I'm running the 
>> tests against a distribution built by CI.
> 
> I don't quite see the relationship here. It seems to me like you could this 
> without what you're talking about.

Right. Either leaving out tasks or substituting tasks means you've got to break 
the implicit contract. Once you've broken it, you can implement the other 
thing. So, it's a shared cost, not a cost specific to leaving out tasks.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Reply via email to