Skip to content

Commit

Permalink
[JENKINS-48348] If task can be run only on master, use shortcut
Browse files Browse the repository at this point in the history
Currently Jenkins to fire WorkflowJob re-calculates the ConstistentHash
for entire cluster even if there is no nodes were updated. If cluster is
big enough (>100 nodes), it becomes a problem, because MD5 is quite
expensive itself plus all this logic comes with high memory footprint.

Using the knowledge that WorkflowJob can be executed only on Jenkins master,
we can create a shortcut that does not do expensive calculation and just
returns Runnable or `null`.

(cherry picked from commit 00ccd23)
  • Loading branch information
Jimilian authored and olivergondza committed Jan 25, 2018
1 parent 2904044 commit eb41a7b
Showing 1 changed file with 26 additions and 8 deletions.
34 changes: 26 additions & 8 deletions core/src/main/java/hudson/model/Queue.java
Expand Up @@ -1691,6 +1691,17 @@ private Runnable makeFlyWeightTaskBuildable(final BuildableItem p){
//we double check if this is a flyweight task
if (p.task instanceof FlyweightTask) {
Jenkins h = Jenkins.getInstance();

Label lbl = p.getAssignedLabel();

if (lbl != null && lbl.equals(h.getSelfLabel())) {
if (h.canTake(p) == null) {
return createFlyWeightTaskRunnable(p, h.toComputer());
} else {
return null;
}
}

Map<Node, Integer> hashSource = new HashMap<Node, Integer>(h.getNodes().size());

// Even if master is configured with zero executors, we may need to run a flyweight task like MatrixProject on it.
Expand All @@ -1703,7 +1714,6 @@ private Runnable makeFlyWeightTaskBuildable(final BuildableItem p){
ConsistentHash<Node> hash = new ConsistentHash<Node>(NODE_HASH);
hash.addAll(hashSource);

Label lbl = p.getAssignedLabel();
String fullDisplayName = p.task.getFullDisplayName();
for (Node n : hash.list(fullDisplayName)) {
final Computer c = n.toComputer();
Expand All @@ -1717,18 +1727,25 @@ private Runnable makeFlyWeightTaskBuildable(final BuildableItem p){
continue;
}

LOGGER.log(Level.FINEST, "Creating flyweight task {0} for computer {1}", new Object[]{fullDisplayName, c.getName()});
return new Runnable() {
@Override public void run() {
c.startFlyWeightTask(new WorkUnitContext(p).createWorkUnit(p.task));
makePending(p);
}
};
return createFlyWeightTaskRunnable(p, c);
}
}
return null;
}

private Runnable createFlyWeightTaskRunnable(final BuildableItem p, final Computer c) {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.log(Level.FINEST, "Creating flyweight task {0} for computer {1}",
new Object[]{p.task.getFullDisplayName(), c.getName()});
}
return new Runnable() {
@Override public void run() {
c.startFlyWeightTask(new WorkUnitContext(p).createWorkUnit(p.task));
makePending(p);
}
};
}

private static Hash<Node> NODE_HASH = new Hash<Node>() {
public String hash(Node node) {
return node.getNodeName();
Expand Down Expand Up @@ -2104,6 +2121,7 @@ public String getInQueueForString() {
* <p>
* This code takes {@link LabelAssignmentAction} into account, then fall back to {@link SubTask#getAssignedLabel()}
*/
@CheckForNull
public Label getAssignedLabel() {
for (LabelAssignmentAction laa : getActions(LabelAssignmentAction.class)) {
Label l = laa.getAssignedLabel(task);
Expand Down

0 comments on commit eb41a7b

Please sign in to comment.