|
6 | 6 | import os
|
7 | 7 | import dateutil.parser
|
8 | 8 |
|
| 9 | +class StwSubTimings: |
| 10 | + def __init__(self): |
| 11 | + self.reset() |
| 12 | + |
| 13 | + def reset(self): |
| 14 | + self.ext_root_scan = 0 |
| 15 | + self.update_rs = 0 |
| 16 | + self.scan_rs = 0 |
| 17 | + self.object_copy = 0 |
| 18 | + self.termination = 0 |
| 19 | + self.other = 0 |
| 20 | + |
| 21 | + def unknown_time(self, total): |
| 22 | + if total: |
| 23 | + return int((total * 1000) - self.ext_root_scan - self.update_rs - self.scan_rs - self.object_copy - self.termination - self.other) |
| 24 | + else: |
| 25 | + return 0 |
| 26 | + |
9 | 27 | class LogParser:
|
10 | 28 | heapG1GCPattern = '\s*\[Eden: ([0-9.]+)([BKMG])\(([0-9.]+)([BKMG])\)->[0-9.BKMG()]+ Survivors: ([0-9.]+)([BKMG])->([0-9.]+)([BKMG]) Heap: ([0-9.]+)([BKMG])\([0-9.BKMG]+\)->([0-9.]+)([BKMG])\([0-9.BKMG]+\)'
|
11 | 29 | parallelPattern = '\s*\[PSYoungGen: ([0-9.]+)([BKMG])->([0-9.]+)([BKMG])\([0-9.MKBG]+\)\] ([0-9.]+)([MKBG])->([0-9.]+)([MKBG])\([0-9.MKBG]+\),'
|
@@ -57,6 +75,7 @@ def __init__(self, input_file):
|
57 | 75 | self.last_minute = -1
|
58 | 76 | self.reset_pause_counts()
|
59 | 77 | self.occupancy_threshold = None
|
| 78 | + self.stw = StwSubTimings() |
60 | 79 |
|
61 | 80 | def cleanup(self):
|
62 | 81 | os.unlink(self.pause_file.name)
|
@@ -103,11 +122,29 @@ def gnuplot(self, name, start, end):
|
103 | 122 | os.system(gnuplot_cmd)
|
104 | 123 | gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:2'" % (self.size, name, xrange, self.pause_file.name)
|
105 | 124 | os.system(gnuplot_cmd)
|
| 125 | + |
| 126 | + # Separate young and mixed stw events |
106 | 127 | gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-young-stw.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:2'" % (self.size, name, xrange, self.young_pause_file.name)
|
107 | 128 | os.system(gnuplot_cmd)
|
108 | 129 | gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-mixed-stw.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:2'" % (self.size, name, xrange, self.mixed_pause_file.name)
|
109 | 130 | os.system(gnuplot_cmd)
|
110 | 131 |
|
| 132 | + # Stw sub-timings |
| 133 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-ext-root-scan.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:3'" % (self.size, name, xrange, self.pause_file.name) |
| 134 | + os.system(gnuplot_cmd) |
| 135 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-update-rs.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:4'" % (self.size, name, xrange, self.pause_file.name) |
| 136 | + os.system(gnuplot_cmd) |
| 137 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-scan-rs.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:5'" % (self.size, name, xrange, self.pause_file.name) |
| 138 | + os.system(gnuplot_cmd) |
| 139 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-object-copy.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:6'" % (self.size, name, xrange, self.pause_file.name) |
| 140 | + os.system(gnuplot_cmd) |
| 141 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-termination.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:7'" % (self.size, name, xrange, self.pause_file.name) |
| 142 | + os.system(gnuplot_cmd) |
| 143 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-other.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:8'" % (self.size, name, xrange, self.pause_file.name) |
| 144 | + os.system(gnuplot_cmd) |
| 145 | + gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-stw-unknown.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:9'" % (self.size, name, xrange, self.pause_file.name) |
| 146 | + os.system(gnuplot_cmd) |
| 147 | + |
111 | 148 | # total pause time
|
112 | 149 | gnuplot_cmd = "gnuplot -e 'set term png size %s; set output \"%s-total-pause.png\"; set xdata time; set timefmt \"%%Y-%%m-%%d:%%H:%%M:%%S\"; %s plot \"%s\" using 1:8 title \"%% of time in gc\"'" % (self.size, name, xrange, self.pause_count_file.name)
|
113 | 150 | os.system(gnuplot_cmd)
|
@@ -210,17 +247,21 @@ def parse_log(self):
|
210 | 247 | if not self.occupancy_threshold:
|
211 | 248 | self.collect_occupancy_threshold_pattern(line)
|
212 | 249 |
|
| 250 | + # collect where time is spent inside stw |
| 251 | + self.collect_stw_sub_timings(line) |
| 252 | + |
213 | 253 | # This needs to be last
|
214 | 254 | if self.line_has_pause_time(line):
|
215 | 255 | self.output_data()
|
| 256 | + self.stw.reset() |
216 | 257 |
|
217 | 258 | def output_data(self):
|
218 | 259 | if self.mixed_duration_count == 0:
|
219 | 260 | self.young_pause_file.write("%s %.6f\n" % (self.timestamp_string(), self.pause_time))
|
220 | 261 | else:
|
221 | 262 | self.mixed_pause_file.write("%s %.6f\n" % (self.timestamp_string(), self.pause_time))
|
222 |
| - |
223 |
| - self.pause_file.write("%s %.6f\n" % (self.timestamp_string(), self.pause_time)) |
| 263 | + |
| 264 | + self.pause_file.write("%s %.6f %d %d %d %d %d %d %d\n" % (self.timestamp_string(), self.pause_time, self.stw.ext_root_scan, self.stw.update_rs, self.stw.scan_rs, self.stw.object_copy, self.stw.termination, self.stw.other, self.stw.unknown_time(self.pause_time))) |
224 | 265 | self.young_file.write("%s %s %s %s %s %s\n" % (self.timestamp_string(), self.pre_gc_young, self.pre_gc_young_target, self.pre_gc_total - self.pre_gc_young, self.pre_gc_total, self.tenured_delta))
|
225 | 266 |
|
226 | 267 | # clean this up, full_gc's should probably graph
|
@@ -337,6 +378,24 @@ def collect_reclaimable(self, line):
|
337 | 378 | if m and int(float(m.group(2))) >= int(m.group(3)) and self.timestamp:
|
338 | 379 | self.reclaimable_file.write("%s %d\n" % (self.timestamp_string(), long(m.group(1)) / 1048576))
|
339 | 380 |
|
| 381 | + def collect_stw_sub_timings(self, line): |
| 382 | + if re.match('^[ ]+\[.*', line): |
| 383 | + self.stw.ext_root_scan = self.parseMaxTiming('Ext Root Scanning', line, self.stw.ext_root_scan) |
| 384 | + self.stw.update_rs = self.parseMaxTiming('Update RS', line, self.stw.update_rs) |
| 385 | + self.stw.scan_rs = self.parseMaxTiming('Scan RS', line, self.stw.scan_rs) |
| 386 | + self.stw.object_copy = self.parseMaxTiming('Object Copy', line, self.stw.object_copy) |
| 387 | + self.stw.termination = self.parseMaxTiming('Termination', line, self.stw.termination) |
| 388 | + m = re.match('^[ ]+\[Other: ([0-9.]+).*', line) |
| 389 | + if m: |
| 390 | + self.stw.other = int(float(m.group(1))) |
| 391 | + |
| 392 | + def parseMaxTiming(self, term, line, current_value): |
| 393 | + m = re.match("^[ ]+\[%s .* Max: ([0-9]+)\.[0-9],.*" % (term), line) |
| 394 | + if m: |
| 395 | + return int(float(m.group(1))) |
| 396 | + else: |
| 397 | + return current_value |
| 398 | + |
340 | 399 | def line_has_gc(self, line):
|
341 | 400 | m = re.match(LogParser.heapG1GCPattern, line, flags=0)
|
342 | 401 | if m:
|
|
0 commit comments