1919
2020import java .time .Duration ;
2121import java .time .Instant ;
22+ import java .util .ArrayList ;
23+ import java .util .Collections ;
24+ import java .util .List ;
2225import java .util .Objects ;
2326import java .util .concurrent .TimeUnit ;
2427import java .util .function .Supplier ;
2730import org .apache .commons .lang3 .function .FailableConsumer ;
2831import org .apache .commons .lang3 .function .FailableRunnable ;
2932import org .apache .commons .lang3 .function .FailableSupplier ;
33+ import org .apache .commons .lang3 .tuple .ImmutablePair ;
3034
3135/**
3236 * {@link StopWatch} provides a convenient API for timings.
@@ -248,6 +252,11 @@ public static StopWatch createStarted() {
248252 */
249253 private long stopTimeNanos ;
250254
255+ /**
256+ * The split history list.
257+ */
258+ private List <Split > splitHistory ;
259+
251260 /**
252261 * Constructs a new instance.
253262 */
@@ -326,6 +335,16 @@ public String getMessage() {
326335 return message ;
327336 }
328337
338+ /**
339+ * Gets the split history list.
340+ *
341+ * @return the list of splits.
342+ * @since 3.19.0
343+ */
344+ public List <Split > getSplitHistory () {
345+ return Collections .unmodifiableList (splitHistory );
346+ }
347+
329348 /**
330349 * Gets the <em>elapsed</em> time in nanoseconds.
331350 *
@@ -557,6 +576,7 @@ private long nanosToMillis(final long nanos) {
557576 public void reset () {
558577 runningState = State .UNSTARTED ;
559578 splitState = SplitState .UNSPLIT ;
579+ splitHistory = new ArrayList <>();
560580 }
561581
562582 /**
@@ -626,6 +646,23 @@ public void split() {
626646 splitState = SplitState .SPLIT ;
627647 }
628648
649+ /**
650+ * <p>
651+ * Captures the time in ns and records in a history list.
652+ * The label specified is used to identify the current split.
653+ * </p>
654+ *
655+ * @param label A message for string presentation.
656+ * @throws IllegalStateException if the StopWatch is not running.
657+ * @since 3.19.0
658+ */
659+ public void recordSplit (final String label ) {
660+ if (runningState != State .RUNNING ) {
661+ throw new IllegalStateException ("Stopwatch is not running." );
662+ }
663+ splitHistory .add (new Split (label , System .nanoTime ()));
664+ }
665+
629666 /**
630667 * Starts this StopWatch.
631668 *
@@ -645,6 +682,7 @@ public void start() {
645682 startTimeNanos = System .nanoTime ();
646683 startInstant = Instant .now ();
647684 runningState = State .RUNNING ;
685+ splitHistory = new ArrayList <>();
648686 }
649687
650688 /**
@@ -746,4 +784,45 @@ public void unsplit() {
746784 splitState = SplitState .UNSPLIT ;
747785 }
748786
787+ /**
788+ * Class to store details of each split.
789+ * @since 3.19.0
790+ */
791+ public static final class Split extends ImmutablePair <String , Long > {
792+
793+ /**
794+ * Constructor with label and duration.
795+ * @param label Label for this split.
796+ * @param timeNanos time in ns.
797+ */
798+ public Split (String label , Long timeNanos ) {
799+ super (label , timeNanos );
800+ }
801+
802+ /**
803+ * Get the label of this split.
804+ * @return label.
805+ */
806+ public String getLabel () {
807+ return getLeft ();
808+ }
809+
810+ /**
811+ * Get the time in nanoseconds.
812+ * @return time in ns.
813+ */
814+ public Long getTimeNanos () {
815+ return getRight ();
816+ }
817+
818+ /**
819+ * Converts this instance to a handy string.
820+ * @return this instance as a string.
821+ */
822+ @ Override
823+ public String toString () {
824+ return String .format ("Split [label=%s, timeNanos=%d])" , getLabel (), getTimeNanos ());
825+ }
826+ }
827+
749828}
0 commit comments