13
13
// limitations under the License.
14
14
package com .google .devtools .build .lib .worker ;
15
15
16
+ import static com .google .common .collect .ImmutableList .toImmutableList ;
17
+
16
18
import com .google .common .annotations .VisibleForTesting ;
17
19
import com .google .common .collect .ImmutableList ;
18
20
import com .google .common .collect .ImmutableSet ;
22
24
import java .util .Comparator ;
23
25
import java .util .HashSet ;
24
26
import java .util .List ;
27
+ import java .util .Optional ;
25
28
import java .util .Set ;
26
29
import java .util .stream .Collectors ;
27
30
import org .apache .commons .pool2 .PooledObject ;
@@ -53,7 +56,7 @@ public void setReporter(Reporter reporter) {
53
56
54
57
@ Override
55
58
public void run () {
56
- if (options .totalWorkerMemoryLimitMb == 0 ) {
59
+ if (options .totalWorkerMemoryLimitMb == 0 && options . workerMemoryLimitMb == 0 ) {
57
60
return ;
58
61
}
59
62
@@ -69,10 +72,17 @@ public void run() {
69
72
70
73
ImmutableList <WorkerMetric > workerMetrics =
71
74
WorkerMetricsCollector .instance ().collectMetrics ();
72
- try {
73
- evictWorkers (workerMetrics );
74
- } catch (InterruptedException e ) {
75
- break ;
75
+
76
+ if (options .totalWorkerMemoryLimitMb > 0 ) {
77
+ try {
78
+ evictWorkers (workerMetrics );
79
+ } catch (InterruptedException e ) {
80
+ break ;
81
+ }
82
+ }
83
+
84
+ if (options .workerMemoryLimitMb > 0 ) {
85
+ killLargeWorkers (workerMetrics , options .workerMemoryLimitMb );
76
86
}
77
87
}
78
88
@@ -83,6 +93,35 @@ void stopProcessing() {
83
93
isWorking = false ;
84
94
}
85
95
96
+ /** Kills any worker that uses more than {@code limitMb} MB of memory. */
97
+ void killLargeWorkers (ImmutableList <WorkerMetric > workerMetrics , int limitMb ) {
98
+ ImmutableList <WorkerMetric > large =
99
+ workerMetrics .stream ()
100
+ .filter (m -> m .getWorkerStat ().getUsedMemoryInKB () / 1000 > limitMb )
101
+ .collect (toImmutableList ());
102
+
103
+ for (WorkerMetric l : large ) {
104
+ String msg ;
105
+
106
+ ImmutableList <Integer > workerIds = l .getWorkerProperties ().getWorkerIds ();
107
+ Optional <ProcessHandle > ph = ProcessHandle .of (l .getWorkerProperties ().getProcessId ());
108
+ if (ph .isPresent ()) {
109
+ msg =
110
+ String .format (
111
+ "Killing %s worker %s (pid %d) taking %dMB" ,
112
+ l .getWorkerProperties ().getMnemonic (),
113
+ workerIds .size () == 1 ? workerIds .get (0 ) : workerIds ,
114
+ l .getWorkerProperties ().getProcessId (),
115
+ l .getWorkerStat ().getUsedMemoryInKB () / 1000 );
116
+ ph .get ().destroyForcibly ();
117
+ logger .atInfo ().log ("%s" , msg );
118
+ if (reporter != null ) {
119
+ reporter .handle (Event .info (msg ));
120
+ }
121
+ }
122
+ }
123
+ }
124
+
86
125
@ VisibleForTesting // productionVisibility = Visibility.PRIVATE
87
126
void evictWorkers (ImmutableList <WorkerMetric > workerMetrics ) throws InterruptedException {
88
127
0 commit comments