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 | ||