8134150: Make Timing both threadsafe and efficient
authorattila
Mon, 24 Aug 2015 09:11:46 +0200
changeset 32315 aa64591f534b
parent 32314 8f7d23d3b1ad
child 32316 5d7dd8dc7729
8134150: Make Timing both threadsafe and efficient Reviewed-by: jlaskey, sundar
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java	Sun Aug 23 10:02:14 2015 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Timing.java	Mon Aug 24 09:11:46 2015 +0200
@@ -28,12 +28,14 @@
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.function.Function;
 import java.util.function.Supplier;
-
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -156,11 +158,12 @@
     }
 
     final class TimeSupplier implements Supplier<String> {
-        private final Map<String, Long> timings;
-
-        TimeSupplier() {
-            timings   = new LinkedHashMap<>();
-        }
+        private final Map<String, LongAdder> timings = new ConcurrentHashMap<>();
+        private final LinkedBlockingQueue<String> orderedTimingNames = new LinkedBlockingQueue<>();
+        private final Function<String, LongAdder> newTimingCreator = s -> {
+            orderedTimingNames.add(s);
+            return new LongAdder();
+        };
 
         String[] getStrings() {
             final List<String> strs = new ArrayList<>();
@@ -184,26 +187,26 @@
             int  maxKeyLength = 0;
             int  maxValueLength = 0;
 
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final Map.Entry<String, LongAdder> entry : timings.entrySet()) {
                 maxKeyLength   = Math.max(maxKeyLength, entry.getKey().length());
-                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length());
+                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue().longValue()).length());
             }
             maxKeyLength++;
 
             final StringBuilder sb = new StringBuilder();
             sb.append("Accumulated compilation phase timings:\n\n");
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final String timingName: orderedTimingNames) {
                 int len;
 
                 len = sb.length();
-                sb.append(entry.getKey());
+                sb.append(timingName);
                 len = sb.length() - len;
 
                 while (len++ < maxKeyLength) {
                     sb.append(' ');
                 }
 
-                final Long duration = entry.getValue();
+                final long duration = timings.get(timingName).longValue();
                 final String strDuration = toMillisPrint(duration);
                 len = strDuration.length();
                 for (int i = 0; i < maxValueLength - len; i++) {
@@ -233,11 +236,7 @@
         }
 
         private void accumulateTime(final String module, final long duration) {
-            Long accumulatedTime = timings.get(module);
-            if (accumulatedTime == null) {
-                accumulatedTime = 0L;
-            }
-            timings.put(module, accumulatedTime + duration);
+            timings.computeIfAbsent(module, newTimingCreator).add(duration);
         }
     }
 }