Mon, 24 Aug 2015 09:11:46 +0200
8134150: Make Timing both threadsafe and efficient
Reviewed-by: jlaskey, sundar
src/jdk/nashorn/internal/runtime/Timing.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/jdk/nashorn/internal/runtime/Timing.java Tue Sep 15 16:17:33 2015 +0530 1.2 +++ b/src/jdk/nashorn/internal/runtime/Timing.java Mon Aug 24 09:11:46 2015 +0200 1.3 @@ -28,12 +28,14 @@ 1.4 import java.io.IOException; 1.5 import java.io.StringReader; 1.6 import java.util.ArrayList; 1.7 -import java.util.LinkedHashMap; 1.8 import java.util.List; 1.9 import java.util.Map; 1.10 +import java.util.concurrent.ConcurrentHashMap; 1.11 +import java.util.concurrent.LinkedBlockingQueue; 1.12 import java.util.concurrent.TimeUnit; 1.13 +import java.util.concurrent.atomic.LongAdder; 1.14 +import java.util.function.Function; 1.15 import java.util.function.Supplier; 1.16 - 1.17 import jdk.nashorn.internal.codegen.CompileUnit; 1.18 import jdk.nashorn.internal.runtime.logging.DebugLogger; 1.19 import jdk.nashorn.internal.runtime.logging.Loggable; 1.20 @@ -156,11 +158,15 @@ 1.21 } 1.22 1.23 final class TimeSupplier implements Supplier<String> { 1.24 - private final Map<String, Long> timings; 1.25 - 1.26 - TimeSupplier() { 1.27 - timings = new LinkedHashMap<>(); 1.28 - } 1.29 + private final Map<String, LongAdder> timings = new ConcurrentHashMap<>(); 1.30 + private final LinkedBlockingQueue<String> orderedTimingNames = new LinkedBlockingQueue<>(); 1.31 + private final Function<String, LongAdder> newTimingCreator = new Function<String, LongAdder>() { 1.32 + @Override 1.33 + public LongAdder apply(final String s) { 1.34 + orderedTimingNames.add(s); 1.35 + return new LongAdder(); 1.36 + } 1.37 + }; 1.38 1.39 String[] getStrings() { 1.40 final List<String> strs = new ArrayList<>(); 1.41 @@ -184,26 +190,26 @@ 1.42 int maxKeyLength = 0; 1.43 int maxValueLength = 0; 1.44 1.45 - for (final Map.Entry<String, Long> entry : timings.entrySet()) { 1.46 + for (final Map.Entry<String, LongAdder> entry : timings.entrySet()) { 1.47 maxKeyLength = Math.max(maxKeyLength, entry.getKey().length()); 1.48 - maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length()); 1.49 + maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue().longValue()).length()); 1.50 } 1.51 maxKeyLength++; 1.52 1.53 final StringBuilder sb = new StringBuilder(); 1.54 sb.append("Accumulated compilation phase timings:\n\n"); 1.55 - for (final Map.Entry<String, Long> entry : timings.entrySet()) { 1.56 + for (final String timingName: orderedTimingNames) { 1.57 int len; 1.58 1.59 len = sb.length(); 1.60 - sb.append(entry.getKey()); 1.61 + sb.append(timingName); 1.62 len = sb.length() - len; 1.63 1.64 while (len++ < maxKeyLength) { 1.65 sb.append(' '); 1.66 } 1.67 1.68 - final Long duration = entry.getValue(); 1.69 + final long duration = timings.get(timingName).longValue(); 1.70 final String strDuration = toMillisPrint(duration); 1.71 len = strDuration.length(); 1.72 for (int i = 0; i < maxValueLength - len; i++) { 1.73 @@ -233,11 +239,7 @@ 1.74 } 1.75 1.76 private void accumulateTime(final String module, final long duration) { 1.77 - Long accumulatedTime = timings.get(module); 1.78 - if (accumulatedTime == null) { 1.79 - accumulatedTime = 0L; 1.80 - } 1.81 - timings.put(module, accumulatedTime + duration); 1.82 + timings.computeIfAbsent(module, newTimingCreator).add(duration); 1.83 } 1.84 } 1.85 }