17
17
import static com .google .common .base .Preconditions .checkState ;
18
18
19
19
import com .google .common .annotations .VisibleForTesting ;
20
+ import com .google .common .base .Preconditions ;
20
21
import com .google .common .base .Predicate ;
21
22
import com .google .common .collect .ImmutableList ;
22
23
import com .google .common .collect .ImmutableSet ;
@@ -306,9 +307,12 @@ ImmutableList<SlowTask> getSlowestTasks() {
306
307
307
308
private Clock clock ;
308
309
private Set <ProfilerTask > profiledTasks ;
309
- private volatile long profileStartTime ;
310
+ private volatile boolean active = false ;
310
311
private volatile boolean recordAllDurations = false ;
311
- private Duration profileCpuStartTime ;
312
+ private Duration profileCpuStartTime = Duration .ZERO ;
313
+ private Duration profileCpuEndTime = Duration .ZERO ;
314
+ private Duration profileStartTime = Duration .ZERO ;
315
+ private Duration profileEndTime = Duration .ZERO ;
312
316
313
317
/**
314
318
* The reference to the current writer, if any. If the referenced writer is null, then disk writes
@@ -376,7 +380,8 @@ private void initHistograms() {
376
380
// stop instead? However, this is currently only called from one location in a module, and that
377
381
// can't call stop itself. What to do?
378
382
public synchronized ImmutableList <StatRecorder > getTasksHistograms () {
379
- return isActive () ? ImmutableList .copyOf (tasksHistograms ) : ImmutableList .of ();
383
+ Preconditions .checkState (isActive ());
384
+ return ImmutableList .copyOf (tasksHistograms );
380
385
}
381
386
382
387
public static Profiler instance () {
@@ -393,14 +398,12 @@ public static long nanoTimeMaybe() {
393
398
return -1 ;
394
399
}
395
400
396
- // Returns the elapsed wall clock time since the profile has been started or null if inactive.
397
- @ Nullable
398
- public static Duration elapsedTimeMaybe () {
399
- if (instance .isActive ()) {
400
- return Duration .ofNanos (instance .clock .nanoTime ())
401
- .minus (Duration .ofNanos (instance .profileStartTime ));
402
- }
403
- return null ;
401
+ // Returns the elapsed wall clock time since the profile has been started.
402
+ public static Duration getProfileElapsedTime () {
403
+ Duration endTime =
404
+ instance .isActive () ? Duration .ofNanos (instance .clock .nanoTime ()) : instance .profileEndTime ;
405
+
406
+ return endTime .minus (instance .profileStartTime );
404
407
}
405
408
406
409
private static Duration getProcessCpuTime () {
@@ -409,13 +412,10 @@ private static Duration getProcessCpuTime() {
409
412
return Duration .ofNanos (bean .getProcessCpuTime ());
410
413
}
411
414
412
- // Returns the CPU time since the profile has been started or null if inactive.
413
- @ Nullable
414
- public static Duration getProcessCpuTimeMaybe () {
415
- if (instance ().isActive ()) {
416
- return getProcessCpuTime ().minus (instance ().profileCpuStartTime );
417
- }
418
- return null ;
415
+ // Returns the CPU time since the profile has been started.
416
+ public static Duration getServerProcessCpuTime () {
417
+ Duration cpuEndTime = instance .isActive () ? getProcessCpuTime () : instance .profileCpuEndTime ;
418
+ return cpuEndTime .minus (instance .profileCpuStartTime );
419
419
}
420
420
421
421
/**
@@ -447,7 +447,8 @@ public synchronized void start(
447
447
boolean collectTaskHistograms ,
448
448
LocalResourceCollector localResourceCollector )
449
449
throws IOException {
450
- checkState (!isActive (), "Profiler already active" );
450
+ checkState (!active , "Profiler already active" );
451
+
451
452
initHistograms ();
452
453
453
454
this .profiledTasks = profiledTasks .isEmpty () ? profiledTasks : EnumSet .copyOf (profiledTasks );
@@ -484,8 +485,9 @@ public synchronized void start(
484
485
this .writerRef .set (writer );
485
486
486
487
// Activate profiler.
487
- profileStartTime = execStartTimeNanos ;
488
+ profileStartTime = Duration . ofNanos ( execStartTimeNanos ) ;
488
489
profileCpuStartTime = getProcessCpuTime ();
490
+ active = true ;
489
491
490
492
this .localResourceCollector = localResourceCollector ;
491
493
// Start collecting Bazel and system-wide CPU metric collection.
@@ -553,24 +555,41 @@ private boolean hasNonZeroValues(Map<ProfilerTask, double[]> countersSeriesMap)
553
555
* will no longer be recorded in the profile.
554
556
*/
555
557
public synchronized void stop () throws IOException {
556
- if (!isActive () ) {
558
+ if (!active ) {
557
559
return ;
558
560
}
559
561
560
562
collectActionCounts ();
561
-
562
563
localResourceCollector .stop ();
563
564
564
565
// Log a final event to update the duration of ProfilePhase.FINISH.
565
566
logEvent (ProfilerTask .INFO , "Finishing" );
566
- JsonTraceFileWriter writer = writerRef .getAndSet (null );
567
- if (writer != null ) {
568
- writer .shutdown ();
569
- writer = null ;
567
+ try {
568
+ JsonTraceFileWriter writer = writerRef .getAndSet (null );
569
+ if (writer != null ) {
570
+ writer .shutdown ();
571
+ writer = null ;
572
+ }
573
+ } finally {
574
+ profileCpuEndTime = getProcessCpuTime ();
575
+ profileEndTime = Duration .ofNanos (clock .nanoTime ());
576
+ active = false ;
570
577
}
578
+ }
579
+
580
+ /**
581
+ * Clears the records the profiler instance keeps.
582
+ *
583
+ * <p>Should always be called between a {@link #stop()} and a subsequent {@link #start}.
584
+ */
585
+ public synchronized void clear () {
586
+ Preconditions .checkState (!active );
587
+
571
588
Arrays .fill (tasksHistograms , null );
572
- profileStartTime = 0L ;
573
- profileCpuStartTime = null ;
589
+ profileStartTime = Duration .ZERO ;
590
+ profileEndTime = Duration .ZERO ;
591
+ profileCpuStartTime = Duration .ZERO ;
592
+ profileCpuEndTime = Duration .ZERO ;
574
593
575
594
for (SlowestTaskAggregator aggregator : slowestTasks ) {
576
595
if (aggregator != null ) {
@@ -583,7 +602,7 @@ public synchronized void stop() throws IOException {
583
602
584
603
/** Returns true iff profiling is currently enabled. */
585
604
public boolean isActive () {
586
- return profileStartTime != 0L ;
605
+ return active ;
587
606
}
588
607
589
608
public boolean isProfiling (ProfilerTask type ) {
0 commit comments