18
18
19
19
import com .google .common .collect .ImmutableList ;
20
20
import com .google .common .collect .ImmutableMap ;
21
- import com .google .devtools .build .lib .analysis .config .CoreOptionConverters .LabelConverter ;
22
21
import com .google .devtools .build .lib .cmdline .Label ;
23
22
import com .google .devtools .build .lib .cmdline .LabelSyntaxException ;
24
23
import com .google .devtools .build .lib .cmdline .PackageIdentifier ;
57
56
import com .google .devtools .build .skyframe .NodeEntry ;
58
57
import com .google .devtools .build .skyframe .QueryableGraph .Reason ;
59
58
import com .google .devtools .build .skyframe .SkyKey ;
59
+ import com .google .devtools .common .options .Converter ;
60
60
import com .google .devtools .common .options .EnumConverter ;
61
61
import com .google .devtools .common .options .Option ;
62
62
import com .google .devtools .common .options .OptionDocumentationCategory ;
63
63
import com .google .devtools .common .options .OptionEffectTag ;
64
64
import com .google .devtools .common .options .OptionsBase ;
65
65
import com .google .devtools .common .options .OptionsParser ;
66
+ import com .google .devtools .common .options .OptionsParsingException ;
66
67
import com .google .devtools .common .options .OptionsParsingResult ;
67
68
import java .io .IOException ;
68
69
import java .io .PrintStream ;
72
73
import java .util .Comparator ;
73
74
import java .util .HashMap ;
74
75
import java .util .List ;
76
+ import java .util .Locale ;
75
77
import java .util .Map ;
76
78
import java .util .Optional ;
77
79
import javax .annotation .Nullable ;
90
92
shortDescription = "Dumps the internal state of the %{product} server process." ,
91
93
binaryStdOut = true )
92
94
public class DumpCommand implements BlazeCommand {
93
-
94
95
/** How to dump Skyframe memory. */
95
- public enum MemoryCollectionMode {
96
- NONE , // Memory dumping disabled
97
- SHALLOW , // Dump the objects owned by a single SkyValue
98
- DEEP , // Dump objects reachable from a single SkyValue
99
- }
100
-
101
- /** Converter for {@link MemoryCollectionMode}. */
102
- public static final class MemoryCollectionModeConverter
103
- extends EnumConverter <MemoryCollectionMode > {
104
- public MemoryCollectionModeConverter () {
105
- super (MemoryCollectionMode .class , "memory collection mode" );
106
- }
96
+ private enum MemoryCollectionMode {
97
+ /** Dump the objects owned by a single SkyValue */
98
+ SHALLOW ,
99
+ /** Dump objects reachable from a single SkyValue */
100
+ DEEP ,
107
101
}
108
102
109
103
/** How to display Skyframe memory use. */
110
- public enum MemoryDisplayMode {
104
+ private enum MemoryDisplayMode {
111
105
/** Just a summary line */
112
106
SUMMARY ,
113
107
/** Object count by class */
@@ -116,10 +110,52 @@ public enum MemoryDisplayMode {
116
110
BYTES ,
117
111
}
118
112
113
+ /** Whose memory use we should measure. */
114
+ private enum MemorySubjectType {
115
+ /** Starlark module */
116
+ STARLARK_MODULE ,
117
+ /* Build package */
118
+ PACKAGE ,
119
+ /* Configured target */
120
+ CONFIGURED_TARGET ,
121
+ }
122
+
123
+ private record MemoryMode (
124
+ MemoryCollectionMode collectionMode ,
125
+ MemoryDisplayMode displayMode ,
126
+ MemorySubjectType type ,
127
+ String subject ) {}
128
+
119
129
/** Converter for {@link MemoryCollectionMode}. */
120
- public static final class MemoryDisplayModeConverter extends EnumConverter <MemoryDisplayMode > {
121
- public MemoryDisplayModeConverter () {
122
- super (MemoryDisplayMode .class , "memory display mode" );
130
+ public static final class MemoryModeConverter extends Converter .Contextless <MemoryMode > {
131
+ @ Override
132
+ public String getTypeDescription () {
133
+ return "memory mode" ;
134
+ }
135
+
136
+ @ Override
137
+ public MemoryMode convert (String input ) throws OptionsParsingException {
138
+ // The SkyKey designator is frequently a Label, which usually contains a colon so we must not
139
+ // split the argument into an unlimited number of elements
140
+ String [] items = input .split (":" , 4 );
141
+ if (items .length != 4 ) {
142
+ throw new OptionsParsingException ("Invalid memory" );
143
+ }
144
+
145
+ MemoryCollectionMode collectionMode ;
146
+ MemoryDisplayMode displayMode ;
147
+ MemorySubjectType subjectType ;
148
+
149
+ try {
150
+ collectionMode = MemoryCollectionMode .valueOf (items [0 ].toUpperCase (Locale .ROOT ));
151
+ displayMode = MemoryDisplayMode .valueOf (items [1 ].toUpperCase (Locale .ROOT ));
152
+ subjectType = MemorySubjectType .valueOf (items [2 ].toUpperCase (Locale .ROOT ));
153
+ } catch (IllegalArgumentException e ) {
154
+ throw new OptionsParsingException (
155
+ "Invalid collection mode, display mode or subject type" , e );
156
+ }
157
+
158
+ return new MemoryMode (collectionMode , displayMode , subjectType , items [3 ]);
123
159
}
124
160
}
125
161
@@ -199,55 +235,12 @@ public static class DumpOptions extends OptionsBase {
199
235
200
236
@ Option (
201
237
name = "memory" ,
202
- defaultValue = "none" ,
203
- converter = MemoryCollectionModeConverter .class ,
204
- documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
205
- effectTags = {OptionEffectTag .BAZEL_MONITORING },
206
- help = "Dump the memory use of the given Skyframe node." )
207
- public MemoryCollectionMode memoryCollectionMode ;
208
-
209
- @ Option (
210
- name = "memory_display" ,
211
- defaultValue = "summary" ,
212
- converter = MemoryDisplayModeConverter .class ,
213
- documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
214
- effectTags = {OptionEffectTag .BAZEL_MONITORING },
215
- help = "The way to display the memory collected by --memory." )
216
- public MemoryDisplayMode memoryDisplayMode ;
217
-
218
- @ Option (
219
- name = "memory_starlark_module" ,
220
238
defaultValue = "null" ,
221
- converter = LabelConverter .class ,
239
+ converter = MemoryModeConverter .class ,
222
240
documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
223
241
effectTags = {OptionEffectTag .BAZEL_MONITORING },
224
- help = "The Starlark module whose memory use should be dumped." )
225
- public Label memoryStarlarkModule ;
226
-
227
- @ Option (
228
- name = "memory_package" ,
229
- defaultValue = "null" ,
230
- documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
231
- effectTags = {OptionEffectTag .BAZEL_MONITORING },
232
- help = "The package whose memory use should be dumped." )
233
- public String memoryPackage ;
234
-
235
- @ Option (
236
- name = "memory_configured_target" ,
237
- defaultValue = "null" ,
238
- converter = LabelConverter .class ,
239
- documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
240
- effectTags = {OptionEffectTag .BAZEL_MONITORING },
241
- help = "The label of the configured target whose memory use should be dumped." )
242
- public Label memoryConfiguredTarget ;
243
-
244
- @ Option (
245
- name = "memory_configkey" ,
246
- defaultValue = "null" ,
247
- documentationCategory = OptionDocumentationCategory .OUTPUT_SELECTION ,
248
- effectTags = {OptionEffectTag .BAZEL_MONITORING },
249
- help = "The configuration key of the configured target whose memory use should be dumped." )
250
- public String memoryConfigKey ;
242
+ help = "Dump the memory use of the given Skyframe node." )
243
+ public MemoryMode memory ;
251
244
}
252
245
253
246
/**
@@ -288,7 +281,7 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
288
281
|| dumpOptions .dumpRules
289
282
|| dumpOptions .starlarkMemory != null
290
283
|| dumpOptions .dumpSkyframe != SkyframeDumpOption .OFF
291
- || dumpOptions .memoryCollectionMode != MemoryCollectionMode . NONE ;
284
+ || dumpOptions .memory != null ;
292
285
if (!anyOutput ) {
293
286
Collection <Class <? extends OptionsBase >> optionList = new ArrayList <>();
294
287
optionList .add (DumpOptions .class );
@@ -344,7 +337,7 @@ public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult opti
344
337
}
345
338
}
346
339
347
- if (dumpOptions .memoryCollectionMode != MemoryCollectionMode . NONE ) {
340
+ if (dumpOptions .memory != null ) {
348
341
failure = dumpSkyframeMemory (env , dumpOptions , out );
349
342
}
350
343
@@ -533,47 +526,31 @@ private static BuildConfigurationKey getConfigurationKey(CommandEnvironment env,
533
526
}
534
527
535
528
@ Nullable
536
- private static SkyKey getMemoryDumpSkyKey (CommandEnvironment env , DumpOptions dumpOptions ) {
537
- Reporter reporter = env .getReporter ();
538
-
539
- List <SkyKey > result = new ArrayList <>();
540
-
541
- if (dumpOptions .memoryStarlarkModule != null ) {
542
- result .add (BzlLoadValue .keyForBuild (dumpOptions .memoryStarlarkModule ));
543
- }
544
-
545
- if (dumpOptions .memoryPackage != null ) {
546
- PackageIdentifier identifier ;
547
- try {
548
- identifier = PackageIdentifier .parse (dumpOptions .memoryPackage );
549
- } catch (LabelSyntaxException e ) {
550
- reporter .error (null , "Cannot parse package identifier: " + e .getMessage ());
551
- return null ;
552
- }
553
-
554
- result .add (identifier );
555
- }
556
-
557
- if (dumpOptions .memoryConfiguredTarget != null ) {
558
- BuildConfigurationKey configurationKey =
559
- getConfigurationKey (env , dumpOptions .memoryConfigKey );
560
- if (configurationKey == null ) {
561
- return null ;
562
- }
563
-
564
- result .add (
565
- ConfiguredTargetKey .builder ()
529
+ private static SkyKey getMemoryDumpSkyKey (CommandEnvironment env , MemoryMode memoryMode ) {
530
+ try {
531
+ switch (memoryMode .type ()) {
532
+ case PACKAGE -> {
533
+ return PackageIdentifier .parse (memoryMode .subject );
534
+ }
535
+ case STARLARK_MODULE -> {
536
+ return BzlLoadValue .keyForBuild (Label .parseCanonical (memoryMode .subject ));
537
+ }
538
+ case CONFIGURED_TARGET -> {
539
+ String [] labelAndConfig = memoryMode .subject .split ("@" , 2 );
540
+ BuildConfigurationKey configurationKey =
541
+ getConfigurationKey (env , labelAndConfig .length == 2 ? labelAndConfig [1 ] : null );
542
+ return ConfiguredTargetKey .builder ()
566
543
.setConfigurationKey (configurationKey )
567
- .setLabel (dumpOptions . memoryConfiguredTarget )
568
- .build ()) ;
569
- }
570
-
571
- if ( result . size () != 1 ) {
572
- reporter . error (null , "You must specify exactly one Skyframe node to dump." );
544
+ .setLabel (Label . parseCanonical ( labelAndConfig [ 0 ]) )
545
+ .build ();
546
+ }
547
+ }
548
+ } catch ( LabelSyntaxException e ) {
549
+ env . getReporter (). error (null , "Cannot parse label: " + e . getMessage () );
573
550
return null ;
574
551
}
575
552
576
- return result . get ( 0 );
553
+ throw new IllegalStateException ( );
577
554
}
578
555
579
556
private static void dumpRamByClass (Map <String , Long > memory , PrintStream out ) {
@@ -633,7 +610,7 @@ private static Stats dumpRamReachable(
633
610
private static Optional <BlazeCommandResult > dumpSkyframeMemory (
634
611
CommandEnvironment env , DumpOptions dumpOptions , PrintStream out )
635
612
throws InterruptedException {
636
- SkyKey skyKey = getMemoryDumpSkyKey (env , dumpOptions );
613
+ SkyKey skyKey = getMemoryDumpSkyKey (env , dumpOptions . memory );
637
614
if (skyKey == null ) {
638
615
return Optional .of (
639
616
createFailureResult ("Cannot dump Skyframe memory" , Code .SKYFRAME_MEMORY_DUMP_FAILED ));
@@ -657,13 +634,12 @@ private static Optional<BlazeCommandResult> dumpSkyframeMemory(
657
634
658
635
ConcurrentIdentitySet seen = getBuiltinsSet (env , fieldCache );
659
636
Stats stats =
660
- switch (dumpOptions .memoryCollectionMode ) {
637
+ switch (dumpOptions .memory . collectionMode ) {
661
638
case DEEP -> dumpRamReachable (nodeEntry , fieldCache , memoryAccountant , seen );
662
639
case SHALLOW -> dumpRamShallow (graph , nodeEntry , fieldCache , memoryAccountant , seen );
663
- case NONE -> throw new IllegalStateException ();
664
640
};
665
641
666
- switch (dumpOptions .memoryDisplayMode ) {
642
+ switch (dumpOptions .memory . displayMode ) {
667
643
case SUMMARY ->
668
644
out .printf (
669
645
"%d objects, %d bytes retained\n " , stats .getObjectCount (), stats .getMemoryUse ());
0 commit comments