diff options
| -rw-r--r-- | scripts/pybootchartgui/pybootchartgui/draw.py | 77 | ||||
| -rw-r--r-- | scripts/pybootchartgui/pybootchartgui/parsing.py | 28 | ||||
| -rw-r--r-- | scripts/pybootchartgui/pybootchartgui/samples.py | 17 |
3 files changed, 122 insertions, 0 deletions
diff --git a/scripts/pybootchartgui/pybootchartgui/draw.py b/scripts/pybootchartgui/pybootchartgui/draw.py index fc708b55c3..a13df3a3fa 100644 --- a/scripts/pybootchartgui/pybootchartgui/draw.py +++ b/scripts/pybootchartgui/pybootchartgui/draw.py | |||
| @@ -80,6 +80,18 @@ MEM_BUFFERS_COLOR = (0.4, 0.4, 0.4, 0.3) | |||
| 80 | # Swap color | 80 | # Swap color |
| 81 | MEM_SWAP_COLOR = DISK_TPUT_COLOR | 81 | MEM_SWAP_COLOR = DISK_TPUT_COLOR |
| 82 | 82 | ||
| 83 | # avg10 CPU pressure color | ||
| 84 | CPU_PRESSURE_AVG10_COLOR = (0.0, 0.0, 0.0, 1.0) | ||
| 85 | # delta total CPU pressure color | ||
| 86 | CPU_PRESSURE_TOTAL_COLOR = CPU_COLOR | ||
| 87 | # avg10 IO pressure color | ||
| 88 | IO_PRESSURE_AVG10_COLOR = (0.0, 0.0, 0.0, 1.0) | ||
| 89 | # delta total IO pressure color | ||
| 90 | IO_PRESSURE_TOTAL_COLOR = IO_COLOR | ||
| 91 | |||
| 92 | |||
| 93 | |||
| 94 | |||
| 83 | # Process border color. | 95 | # Process border color. |
| 84 | PROC_BORDER_COLOR = (0.71, 0.71, 0.71, 1.0) | 96 | PROC_BORDER_COLOR = (0.71, 0.71, 0.71, 1.0) |
| 85 | # Waiting process color. | 97 | # Waiting process color. |
| @@ -415,6 +427,71 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w): | |||
| 415 | 427 | ||
| 416 | curr_y = curr_y + 30 + bar_h | 428 | curr_y = curr_y + 30 + bar_h |
| 417 | 429 | ||
| 430 | # render CPU pressure chart | ||
| 431 | if trace.cpu_pressure: | ||
| 432 | draw_legend_line(ctx, "avg10 CPU Pressure", CPU_PRESSURE_AVG10_COLOR, off_x, curr_y+20, leg_s) | ||
| 433 | draw_legend_box(ctx, "delta total CPU Pressure", CPU_PRESSURE_TOTAL_COLOR, off_x + 140, curr_y+20, leg_s) | ||
| 434 | |||
| 435 | # render delta total cpu | ||
| 436 | chart_rect = (off_x, curr_y+30, w, bar_h) | ||
| 437 | if clip_visible (clip, chart_rect): | ||
| 438 | draw_box_ticks (ctx, chart_rect, sec_w) | ||
| 439 | draw_annotations (ctx, proc_tree, trace.times, chart_rect) | ||
| 440 | draw_chart (ctx, CPU_PRESSURE_TOTAL_COLOR, True, chart_rect, \ | ||
| 441 | [(sample.time, sample.deltaTotal) for sample in trace.cpu_pressure], \ | ||
| 442 | proc_tree, None) | ||
| 443 | |||
| 444 | # render avg10 cpu | ||
| 445 | max_sample = max (trace.cpu_pressure, key = lambda s: s.avg10) | ||
| 446 | if clip_visible (clip, chart_rect): | ||
| 447 | draw_chart (ctx, CPU_PRESSURE_AVG10_COLOR, False, chart_rect, \ | ||
| 448 | [(sample.time, sample.avg10) for sample in trace.cpu_pressure], \ | ||
| 449 | proc_tree, None) | ||
| 450 | |||
| 451 | pos_x = off_x + ((max_sample.time - proc_tree.start_time) * w / proc_tree.duration) | ||
| 452 | |||
| 453 | shift_x, shift_y = -20, 20 | ||
| 454 | if (pos_x < off_x + 245): | ||
| 455 | shift_x, shift_y = 5, 40 | ||
| 456 | |||
| 457 | |||
| 458 | label = "%d%%" % (max_sample.avg10) | ||
| 459 | draw_text (ctx, label, CPU_PRESSURE_AVG10_COLOR, pos_x + shift_x, curr_y + shift_y) | ||
| 460 | |||
| 461 | curr_y = curr_y + 30 + bar_h | ||
| 462 | |||
| 463 | # render delta total io | ||
| 464 | if trace.io_pressure: | ||
| 465 | draw_legend_line(ctx, "avg10 I/O Pressure", IO_PRESSURE_AVG10_COLOR, off_x, curr_y+20, leg_s) | ||
| 466 | draw_legend_box(ctx, "delta total I/O Pressure", IO_PRESSURE_TOTAL_COLOR, off_x + 140, curr_y+20, leg_s) | ||
| 467 | |||
| 468 | # render avg10 io | ||
| 469 | chart_rect = (off_x, curr_y+30, w, bar_h) | ||
| 470 | if clip_visible (clip, chart_rect): | ||
| 471 | draw_box_ticks (ctx, chart_rect, sec_w) | ||
| 472 | draw_annotations (ctx, proc_tree, trace.times, chart_rect) | ||
| 473 | draw_chart (ctx, IO_PRESSURE_TOTAL_COLOR, True, chart_rect, \ | ||
| 474 | [(sample.time, sample.deltaTotal) for sample in trace.io_pressure], \ | ||
| 475 | proc_tree, None) | ||
| 476 | |||
| 477 | # render io pressure | ||
| 478 | max_sample = max (trace.io_pressure, key = lambda s: s.avg10) | ||
| 479 | if clip_visible (clip, chart_rect): | ||
| 480 | draw_chart (ctx, IO_PRESSURE_AVG10_COLOR, False, chart_rect, \ | ||
| 481 | [(sample.time, sample.avg10) for sample in trace.io_pressure], \ | ||
| 482 | proc_tree, None) | ||
| 483 | |||
| 484 | pos_x = off_x + ((max_sample.time - proc_tree.start_time) * w / proc_tree.duration) | ||
| 485 | |||
| 486 | shift_x, shift_y = -20, 20 | ||
| 487 | if (pos_x < off_x + 245): | ||
| 488 | shift_x, shift_y = 5, 40 | ||
| 489 | |||
| 490 | label = "%d%%" % (max_sample.avg10) | ||
| 491 | draw_text (ctx, label, IO_PRESSURE_AVG10_COLOR, pos_x + shift_x, curr_y + shift_y) | ||
| 492 | |||
| 493 | curr_y = curr_y + 30 + bar_h | ||
| 494 | |||
| 418 | # render disk space usage | 495 | # render disk space usage |
| 419 | # | 496 | # |
| 420 | # Draws the amount of disk space used on each volume relative to the | 497 | # Draws the amount of disk space used on each volume relative to the |
diff --git a/scripts/pybootchartgui/pybootchartgui/parsing.py b/scripts/pybootchartgui/pybootchartgui/parsing.py index b42dac6b88..004d6fb953 100644 --- a/scripts/pybootchartgui/pybootchartgui/parsing.py +++ b/scripts/pybootchartgui/pybootchartgui/parsing.py | |||
| @@ -49,6 +49,8 @@ class Trace: | |||
| 49 | self.parent_map = None | 49 | self.parent_map = None |
| 50 | self.mem_stats = [] | 50 | self.mem_stats = [] |
| 51 | self.monitor_disk = None | 51 | self.monitor_disk = None |
| 52 | self.cpu_pressure = [] | ||
| 53 | self.io_pressure = [] | ||
| 52 | self.times = [] # Always empty, but expected by draw.py when drawing system charts. | 54 | self.times = [] # Always empty, but expected by draw.py when drawing system charts. |
| 53 | 55 | ||
| 54 | if len(paths): | 56 | if len(paths): |
| @@ -554,6 +556,27 @@ def _parse_monitor_disk_log(file): | |||
| 554 | 556 | ||
| 555 | return disk_stats | 557 | return disk_stats |
| 556 | 558 | ||
| 559 | def _parse_pressure_logs(file, filename): | ||
| 560 | """ | ||
| 561 | Parse file for "some" pressure with 'avg10', 'avg60' 'avg300' and delta total values | ||
| 562 | (in that order) directly stored on one line for both CPU and IO, based on filename. | ||
| 563 | """ | ||
| 564 | pressure_stats = [] | ||
| 565 | if filename == "cpu.log": | ||
| 566 | SamplingClass = CPUPressureSample | ||
| 567 | else: | ||
| 568 | SamplingClass = IOPressureSample | ||
| 569 | for time, lines in _parse_timed_blocks(file): | ||
| 570 | for line in lines: | ||
| 571 | if not line: continue | ||
| 572 | tokens = line.split() | ||
| 573 | avg10 = float(tokens[0]) | ||
| 574 | avg60 = float(tokens[1]) | ||
| 575 | avg300 = float(tokens[2]) | ||
| 576 | delta = float(tokens[3]) | ||
| 577 | pressure_stats.append(SamplingClass(time, avg10, avg60, avg300, delta)) | ||
| 578 | |||
| 579 | return pressure_stats | ||
| 557 | 580 | ||
| 558 | # if we boot the kernel with: initcall_debug printk.time=1 we can | 581 | # if we boot the kernel with: initcall_debug printk.time=1 we can |
| 559 | # get all manner of interesting data from the dmesg output | 582 | # get all manner of interesting data from the dmesg output |
| @@ -741,6 +764,11 @@ def _do_parse(writer, state, filename, file): | |||
| 741 | state.cmdline = _parse_cmdline_log(writer, file) | 764 | state.cmdline = _parse_cmdline_log(writer, file) |
| 742 | elif name == "monitor_disk.log": | 765 | elif name == "monitor_disk.log": |
| 743 | state.monitor_disk = _parse_monitor_disk_log(file) | 766 | state.monitor_disk = _parse_monitor_disk_log(file) |
| 767 | #pressure logs are in a subdirectory | ||
| 768 | elif name == "cpu.log": | ||
| 769 | state.cpu_pressure = _parse_pressure_logs(file, name) | ||
| 770 | elif name == "io.log": | ||
| 771 | state.io_pressure = _parse_pressure_logs(file, name) | ||
| 744 | elif not filename.endswith('.log'): | 772 | elif not filename.endswith('.log'): |
| 745 | _parse_bitbake_buildstats(writer, state, filename, file) | 773 | _parse_bitbake_buildstats(writer, state, filename, file) |
| 746 | t2 = time.process_time() | 774 | t2 = time.process_time() |
diff --git a/scripts/pybootchartgui/pybootchartgui/samples.py b/scripts/pybootchartgui/pybootchartgui/samples.py index 9fc309b3ab..472dc27be0 100644 --- a/scripts/pybootchartgui/pybootchartgui/samples.py +++ b/scripts/pybootchartgui/pybootchartgui/samples.py | |||
| @@ -37,6 +37,23 @@ class CPUSample: | |||
| 37 | return str(self.time) + "\t" + str(self.user) + "\t" + \ | 37 | return str(self.time) + "\t" + str(self.user) + "\t" + \ |
| 38 | str(self.sys) + "\t" + str(self.io) + "\t" + str (self.swap) | 38 | str(self.sys) + "\t" + str(self.io) + "\t" + str (self.swap) |
| 39 | 39 | ||
| 40 | class CPUPressureSample: | ||
| 41 | def __init__(self, time, avg10, avg60, avg300, deltaTotal): | ||
| 42 | self.time = time | ||
| 43 | self.avg10 = avg10 | ||
| 44 | self.avg60 = avg60 | ||
| 45 | self.avg300 = avg300 | ||
| 46 | self.deltaTotal = deltaTotal | ||
| 47 | |||
| 48 | class IOPressureSample: | ||
| 49 | def __init__(self, time, avg10, avg60, avg300, deltaTotal): | ||
| 50 | self.time = time | ||
| 51 | self.avg10 = avg10 | ||
| 52 | self.avg60 = avg60 | ||
| 53 | self.avg300 = avg300 | ||
| 54 | self.deltaTotal = deltaTotal | ||
| 55 | |||
| 56 | |||
| 40 | class MemSample: | 57 | class MemSample: |
| 41 | used_values = ('MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree',) | 58 | used_values = ('MemTotal', 'MemFree', 'Buffers', 'Cached', 'SwapTotal', 'SwapFree',) |
| 42 | 59 | ||
