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

[FIXED JENKINS-34722] Performance improvement to not load all jobs #100

Merged
merged 4 commits into from May 20, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -24,15 +24,8 @@
*/
package au.com.centrumsystems.hudson.plugin.util;

import hudson.model.Action;
import hudson.model.ParameterValue;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Cause;
import hudson.model.*;
Copy link
Member

Choose a reason for hiding this comment

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

BTW we typically discourage star imports.

Copy link
Member

Choose a reason for hiding this comment

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

In fact Checkstyle is failing the build in this case.

import hudson.model.Cause.UpstreamCause;
import hudson.model.CauseAction;
import hudson.model.FileParameterValue;
import hudson.model.ParametersAction;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -61,19 +54,24 @@ public final class BuildUtil {
public static AbstractBuild<?, ?> getDownstreamBuild(final AbstractProject<?, ?> downstreamProject,
final AbstractBuild<?, ?> upstreamBuild) {
if ((downstreamProject != null) && (upstreamBuild != null)) {
// We set the MAX_DOWNSTREAM_DEPTH to search everything. This is to prevent breaking current behavior. This
// flag can be set via groovy console, so users can adjust this parameter without having to restart Jenkins.
int max_downstream_depth = Integer.getInteger(BuildUtil.class.getCanonicalName() + ".MAX_DOWNSTREAM_DEPTH", Integer.MAX_VALUE);

// This can cause a major performance issue specifically when it tries to search through all of the builds,
// and it never finds the correct upstream cause action. It might never be able to find the correct cause action because
// a pipeline was executed and later terminated early. If that is the case, then we go through the entire list
// of builds even though we terminated early.
//
// To counter any potential performance issue the system property au.com.centurmsystems.hudson.plugin.util.BuildUtil.MAX_DOWNSTREAM_DEPTH
// can be set which sets the max limit for how many builds should be loaded for the max depth.

@SuppressWarnings("unchecked")
final List<AbstractBuild<?, ?>> downstreamBuilds = (List<AbstractBuild<?, ?>>) downstreamProject.getBuilds();
final List<AbstractBuild<?, ?>> downstreamBuilds = (List<AbstractBuild<?, ?>>) downstreamProject.getBuilds().limit(max_downstream_depth);
for (final AbstractBuild<?, ?> innerBuild : downstreamBuilds) {
for (final CauseAction action : innerBuild.getActions(CauseAction.class)) {
for (final Cause cause : action.getCauses()) {
if (cause instanceof UpstreamCause) {
final UpstreamCause upstreamCause = (UpstreamCause) cause;
if (upstreamCause.getUpstreamProject().equals(upstreamBuild.getProject().getFullName())
&& (upstreamCause.getUpstreamBuild() == upstreamBuild.getNumber())) {
return innerBuild;
}
}
}
final UpstreamCause cause = innerBuild.getCause(UpstreamCause.class);
if (cause != null && cause.pointsTo(upstreamBuild)) {
return innerBuild;
}
}
}
Expand Down
Expand Up @@ -38,6 +38,9 @@
import org.junit.Before;
import org.junit.Test;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.RunLoadCounter;

import java.util.concurrent.Callable;

public class BuildUtilTest extends HudsonTestCase {

Expand All @@ -47,6 +50,40 @@ public void setUp() throws Exception {
super.setUp();
}

@Test
public void testGetDownstreamBuildWithLimit() throws Exception {
int max_upstream_depth = 3;
int total_proj2_builds = 5;
System.setProperty(BuildUtil.class.getCanonicalName() + ".MAX_DOWNSTREAM_DEPTH", String.valueOf(max_upstream_depth));

final FreeStyleProject proj1 = createFreeStyleProject();
final FreeStyleProject proj2 = createFreeStyleProject();


final FreeStyleBuild freeStyleBuild = proj1.scheduleBuild2(0).get();
assertBuildStatusSuccess(freeStyleBuild);

proj1.getPublishersList().add(new BuildTrigger(proj2.getName(), true));

jenkins.rebuildDependencyGraph();

// Schedule a build 10 times
Copy link
Member

Choose a reason for hiding this comment

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

🐜 this comment is incorrect. It is 5, not 10.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

for (int i = 0; i < total_proj2_builds; i++) {
assertBuildStatusSuccess(proj1.scheduleBuild2(0));
waitUntilNoActivity();
}
assertEquals("Proj2 does not have the correct number of builds.", total_proj2_builds + 1, proj2.getNextBuildNumber());
RunLoadCounter.prepare(proj2);

assertFalse(RunLoadCounter.assertMaxLoads(proj2, max_upstream_depth - 1, new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return BuildUtil.getDownstreamBuild(proj2, freeStyleBuild) != null;
Copy link
Member

Choose a reason for hiding this comment

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

Easier to understand

assertNull(RunLoadCounter.assertMaxLoads(proj2, max_upstream_depth - 1, new Callable<AbstractBuild<?,?>>() {
    @Override
    public AbstractBuild<?,?> call() throws Exception {
        return BuildUtil.getDownstreamBuild(proj2, freeStyleBuild);
    }
}));

}
}));
}


@Test
public void testGetDownstreamBuild() throws Exception {
final String proj1 = "Proj1";
Expand Down