9292import java .util .NavigableMap ;
9393import java .util .Stack ;
9494import java .util .TreeMap ;
95+ import java .util .concurrent .ConcurrentHashMap ;
9596import java .util .concurrent .CopyOnWriteArrayList ;
9697import java .util .concurrent .ExecutionException ;
9798import java .util .concurrent .Future ;
@@ -384,8 +385,7 @@ enum TimingKind {
384385 }
385386
386387 /** accumulated time in ns of a given {@link TimingKind#name}; {@link String} key for pretty XStream form */
387- @ GuardedBy ("this" )
388- @ CheckForNull Map <String , Long > timings ;
388+ @ NonNull Map <String , Long > timings = new ConcurrentHashMap <>();
389389
390390 @ Deprecated
391391 public CpsFlowExecution (String script , FlowExecutionOwner owner ) throws IOException {
@@ -410,9 +410,14 @@ public CpsFlowExecution(String script, boolean sandbox, FlowExecutionOwner owner
410410 /**
411411 * Perform post-deserialization state resurrection that handles version evolution
412412 */
413+ @ SuppressFBWarnings (value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" , justification = "Could be null if deserialized from old version" )
413414 private Object readResolve () {
414415 if (loadedScripts ==null )
415416 loadedScripts = new HashMap <>(); // field added later
417+ // Convert timings to concurrent hash map
418+ if (!(timings instanceof ConcurrentHashMap )) {
419+ timings = timings == null ? new ConcurrentHashMap <>() : new ConcurrentHashMap <>(timings );
420+ }
416421 return this ;
417422 }
418423
@@ -424,16 +429,7 @@ private Timing(TimingKind kind) {
424429 start = System .nanoTime ();
425430 }
426431 @ Override public void close () {
427- synchronized (CpsFlowExecution .this ) {
428- if (timings == null ) {
429- timings = new HashMap <>();
430- }
431- Long orig = timings .get (kind .name ());
432- if (orig == null ) {
433- orig = 0L ;
434- }
435- timings .put (kind .name (), orig + System .nanoTime () - start );
436- }
432+ timings .merge (kind .name (), System .nanoTime () - start , Long ::sum );
437433 }
438434 }
439435
@@ -448,12 +444,10 @@ Timing time(TimingKind kind) {
448444
449445 static final Logger TIMING_LOGGER = Logger .getLogger (CpsFlowExecution .class .getName () + ".timing" );
450446
451- synchronized void logTimings () {
452- if (timings != null && TIMING_LOGGER .isLoggable (Level .FINE )) {
447+ void logTimings () {
448+ if (TIMING_LOGGER .isLoggable (Level .FINE )) {
453449 Map <String , String > formatted = new TreeMap <>();
454- for (Map .Entry <String , Long > entry : timings .entrySet ()) {
455- formatted .put (entry .getKey (), entry .getValue () / 1000 / 1000 + "ms" );
456- }
450+ timings .forEach ((k , v ) -> formatted .put (k , v / 1000 / 1000 + "ms" ));
457451 TIMING_LOGGER .log (Level .FINE , "timings for {0}: {1}" , new Object [] {owner , formatted });
458452 }
459453 }
@@ -1643,11 +1637,7 @@ public void marshal(Object source, HierarchicalStreamWriter w, MarshallingContex
16431637 if (e .durabilityHint != null ) {
16441638 writeChild (w , context , "durabilityHint" , e .durabilityHint , FlowDurabilityHint .class );
16451639 }
1646- synchronized (e ) {
1647- if (e .timings != null ) {
1648- writeChild (w , context , "timings" , e .timings , Map .class );
1649- }
1650- }
1640+ writeChild (w , context , "timings" , e .timings , Map .class );
16511641 writeChild (w , context , "sandbox" , e .sandbox , Boolean .class );
16521642 if (e .user != null ) {
16531643 writeChild (w , context , "user" , e .user , String .class );
@@ -1931,14 +1921,10 @@ public void autopersist(@NonNull FlowNode n) throws IOException {
19311921 continue ;
19321922 }
19331923 if (exec instanceof CpsFlowExecution ) {
1934- Map <String , Long > timings = ((CpsFlowExecution ) exec ).timings ;
1935- if (timings != null ) {
1936- pw .println ("Timings for " + run + ":" );
1937- for (Map .Entry <String , Long > entry : new TreeMap <>(timings ).entrySet ()) {
1938- pw .println (" " + entry .getKey () + "\t " + entry .getValue () / 1000 / 1000 + "ms" );
1939- }
1940- pw .println ();
1941- }
1924+ Map <String , Long > sortedTimings = new TreeMap <>(((CpsFlowExecution ) exec ).timings );
1925+ pw .println ("Timings for " + run + ":" );
1926+ sortedTimings .forEach ((k , v ) -> pw .println (" " + k + "\t " + v / 1000 / 1000 + "ms" ));
1927+ pw .println ();
19421928 }
19431929 }
19441930 }
0 commit comments