Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maven-like rolling output when the build happens to be linear #271

Merged
merged 1 commit into from
Dec 16, 2020

Conversation

ppalaga
Copy link
Contributor

@ppalaga ppalaga commented Dec 15, 2020

Fix #269

@ppalaga ppalaga changed the title Maven-like rolling output when the build happens to be linear #269 Maven-like rolling output when the build happens to be linear Dec 15, 2020
session.getRequest().getDegreeOfConcurrency()));

final DependencyGraph smartGraph = DependencyGraph.fromMaven(session);
session.setProjectDependencyGraph(smartGraph);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gnodet this is quite a rough way to do it. I was not able to persuade the guice container to prefer my org.apache.maven.graph.GraphBuilder impl. to the default one. So I gave up and did this replacement instead. I would not mind if you veto this and propose something more elegant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, it may be better to not rewrite the graph and just keep the code as it is.
i.e. DependencyGraph and not tie it to ProjectDependencyGraph.

@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

I am a bit more content with 385d77e:

  • Our custom SmartGraphBuilder is properly instantiated via Guice
  • The DependencyGraph now has a width field, that returns 1 if the graph is serial and Integer.MAX_VALUE otherwise. That's enough for the current feature. It can be enhanced later to return the proper width for other purposes.

Copy link
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit more content with 385d77e:

  • Our custom SmartGraphBuilder is properly instantiated via Guice
  • The DependencyGraph now has a width field, that returns 1 if the graph is serial and Integer.MAX_VALUE otherwise. That's enough for the current feature. It can be enhanced later to return the proper width for other purposes.

Would it be possible to keep the DependencyGraph interface independent of maven ? The algorithm I have only depends on the upstream / downstream methods, so having to create MavenProject objects for nothing will make things harder to test.

See https://github.com/gnodet/mvnd/blob/dag-width/daemon/src/test/java/org/mvndaemon/mvnd/builder/DagWidthTest.java

public Stream<MavenProject> getDownstreamProjects(MavenProject project) {
return downstreams.get(project).stream();
}
final boolean serial = !projects.stream().anyMatch(p -> downstreams.get(p).size() > 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check isn't correct imho. In order to use such a check, we'd have to remove dependencies that are redundant. For example
A depends on B
A depends on C
B depends on C
This is a very common scenario (C being the parent, with 2 children), but I think it will fail the check because C will have 2 downstream projects, yet, the build is linear (C -> B -> A).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, is there any case where it returns 1 apart when building a single project ? It looks like the parent/child relationship will make this simple algorithm useless. Am I missing something ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is not perfect, but it works in some simple cases at least and for me it is still an important improvement. As I said, a proper width computation can be added later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can easily port my computation algorithm, provided you keep the DependencyGraph<K> interface.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


final int maxThreads = smartGraph.isSerial() ? 1 : session.getRequest().getDegreeOfConcurrency();
queue.add(new BuildStarted(getCurrentProject(session).getName(), smartGraph.getSortedProjects().size(),
maxThreads));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a branch pending that attempts at computing the maximum width of the graph, let me check its state.

session.getRequest().getDegreeOfConcurrency()));

final DependencyGraph smartGraph = DependencyGraph.fromMaven(session);
session.setProjectDependencyGraph(smartGraph);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, it may be better to not rewrite the graph and just keep the code as it is.
i.e. DependencyGraph and not tie it to ProjectDependencyGraph.

@@ -173,6 +173,11 @@ private boolean doAccept(Message entry) {
this.maxThreads = bs.getMaxThreads();
final int maxThreadsDigits = (int) (Math.log10(maxThreads) + 1);
this.threadsFormat = "%" + (maxThreadsDigits * 3 + 2) + "s";
if (maxThreads == 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use a configuration flag for that ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean some users might not want this auto-rolling? I must say I like it like this. I would not want to add the flag unless somebody explicitly asks for it. Of course, if you personally want this, I'll add it immediately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with the auto-rolling behaviour. Let's advertise the change in the release notes and see if people want a switch. I've read users saying they do really like the buffered output a lot, but for linear builds it may be a bit different.

@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

Would it be possible to keep the DependencyGraph interface independent of maven ? The algorithm I have only depends on the upstream / downstream methods, so having to create MavenProject objects for nothing will make things harder to test.

See https://github.com/gnodet/mvnd/blob/dag-width/daemon/src/test/java/org/mvndaemon/mvnd/builder/DagWidthTest.java

Yeah, that's a valid point. Let me try that.

@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

2708c12 keeps the DependencyGraph interface independent of Maven.

@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

80b66e2: adapted your DagWidth implementation

@@ -29,7 +29,7 @@ public void testRules() {
MavenProject a = newProject("a"), b = newProject("b"), c = newProject("c");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be better to rename the class altogether, given we're testing the SmartProjectDependencyGraph

return Result.success(smartGraph);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I'm a bit skeptic on the benefits of overriding the graph builder to wrap the existing graph by delegating to the standard graph builder, as we have to cast it later to actually access the correct instance.
It may be easier to simply wrap it when needed. If we need to avoid wrapping it multiple times (not sure that's actually the case), we can always cache it in the session / execution context somewhere.
The problem is that it ties us to maven internals (which I'd rather avoid as much as possible) with no real benefits imho.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it ties us to maven internals

That's a valid point

It may be easier to simply wrap it when needed. If we need to avoid wrapping it multiple times (not sure that's actually the case),

Yes, we do. The graph is needed on two locations at least.

we can always cache it in the session / execution context somewhere.

Yeah, storing it somewhere in the session was my first thought. I have not found any general purpose map in the session or in any of its associated classes. Do we have any better option than system properties, ThreadLocal or a static variable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MavenSession.getExecutionRequest().getData() or MavenSession.getRepositorySession().getData() or MavenSession.getRepositorySession().getCache().

Given we want to avoid stale informations, the former may be the better as it won't outlive the current build.

At the moment, it's only used once. I suppose it's used in an additional call to compute the width ?

@gnodet
Copy link
Contributor

gnodet commented Dec 16, 2020

@ppalaga Wouldn't it be easier to just include the changes on the client (when there's a single thread or theres's only a single project) and defer the server side stuff for 0.3.0 ?

@ppalaga ppalaga force-pushed the i269 branch 2 times, most recently from bd596e2 to c3ac2f6 Compare December 16, 2020 17:10
@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

c3ac2f6: DependencyGraph wraps ProjectDependencyGraph and stores it in session.getRequest().getData()

If this iteration is not good enough, I do not mind postponing this.

@gnodet
Copy link
Contributor

gnodet commented Dec 16, 2020

c3ac2f6: DependencyGraph wraps ProjectDependencyGraph and stores it in session.getRequest().getData()

If this iteration is not good enough, I do not mind postponing this.

Ok, let me check asap.

@gnodet
Copy link
Contributor

gnodet commented Dec 16, 2020

@ppalaga Could you just add the following change gnodet@b1d9bd5 ?

Otherwise looks good !

@ppalaga
Copy link
Contributor Author

ppalaga commented Dec 16, 2020

Could you just add the following change gnodet@b1d9bd5 ?

Accepted in 1c5e086

@ppalaga ppalaga merged commit f2cdcf9 into apache:master Dec 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Maven-like rolling output when the build happens to be linear
2 participants