summaryrefslogtreecommitdiffstats
path: root/scripts/pybootchartgui
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/pybootchartgui')
-rw-r--r--scripts/pybootchartgui/pybootchartgui/draw.py62
-rw-r--r--scripts/pybootchartgui/pybootchartgui/parsing.py26
-rw-r--r--scripts/pybootchartgui/pybootchartgui/samples.py11
3 files changed, 99 insertions, 0 deletions
diff --git a/scripts/pybootchartgui/pybootchartgui/draw.py b/scripts/pybootchartgui/pybootchartgui/draw.py
index ec5dd333a1..f0143ad0d6 100644
--- a/scripts/pybootchartgui/pybootchartgui/draw.py
+++ b/scripts/pybootchartgui/pybootchartgui/draw.py
@@ -133,6 +133,16 @@ TASK_COLOR_PACKAGE = (0.0, 1.00, 1.00, 1.0)
133# Package Write RPM/DEB/IPK task color 133# Package Write RPM/DEB/IPK task color
134TASK_COLOR_PACKAGE_WRITE = (0.0, 0.50, 0.50, 1.0) 134TASK_COLOR_PACKAGE_WRITE = (0.0, 0.50, 0.50, 1.0)
135 135
136# Distinct colors used for different disk volumnes.
137# If we have more volumns, colors get re-used.
138VOLUME_COLORS = [
139 (1.0, 1.0, 0.00, 1.0),
140 (0.0, 1.00, 0.00, 1.0),
141 (1.0, 0.00, 1.00, 1.0),
142 (0.0, 0.00, 1.00, 1.0),
143 (0.0, 1.00, 1.00, 1.0),
144]
145
136# Process states 146# Process states
137STATE_UNDEFINED = 0 147STATE_UNDEFINED = 0
138STATE_RUNNING = 1 148STATE_RUNNING = 1
@@ -397,6 +407,58 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w):
397 407
398 curr_y = curr_y + 30 + bar_h 408 curr_y = curr_y + 30 + bar_h
399 409
410 # render disk space usage
411 #
412 # Draws the amount of disk space used on each volume relative to the
413 # lowest recorded amount. The graphs for each volume are stacked above
414 # each other so that total disk usage is visible.
415 if trace.monitor_disk:
416 ctx.set_font_size(LEGEND_FONT_SIZE)
417 # Determine set of volumes for which we have
418 # information and the minimal amount of used disk
419 # space for each. Currently samples are allowed to
420 # not have a values for all volumes; drawing could be
421 # made more efficient if that wasn't the case.
422 volumes = set()
423 min_used = {}
424 for sample in trace.monitor_disk:
425 for volume, used in sample.records.items():
426 volumes.add(volume)
427 if volume not in min_used or min_used[volume] > used:
428 min_used[volume] = used
429 volumes = sorted(list(volumes))
430 disk_scale = 0
431 for i, volume in enumerate(volumes):
432 volume_scale = max([sample.records[volume] - min_used[volume]
433 for sample in trace.monitor_disk
434 if volume in sample.records])
435 # Does not take length of volume name into account, but fixed offset
436 # works okay in practice.
437 draw_legend_box(ctx, '%s (max: %u MiB)' % (volume, volume_scale / 1024 / 1024),
438 VOLUME_COLORS[i % len(VOLUME_COLORS)],
439 off_x + i * 250, curr_y+20, leg_s)
440 disk_scale += volume_scale
441
442 # render used amount of disk space
443 chart_rect = (off_x, curr_y+30, w, bar_h)
444 if clip_visible (clip, chart_rect):
445 draw_box_ticks (ctx, chart_rect, sec_w)
446 draw_annotations (ctx, proc_tree, trace.times, chart_rect)
447 for i in range(len(volumes), 0, -1):
448 draw_chart (ctx, VOLUME_COLORS[(i - 1) % len(VOLUME_COLORS)], True, chart_rect, \
449 [(sample.time,
450 # Sum up used space of all volumes including the current one
451 # so that the graphs appear as stacked on top of each other.
452 reduce(lambda x,y: x+y,
453 [sample.records[volume] - min_used[volume]
454 for volume in volumes[0:i]
455 if volume in sample.records],
456 0))
457 for sample in trace.monitor_disk], \
458 proc_tree, [0, disk_scale])
459
460 curr_y = curr_y + 30 + bar_h
461
400 # render mem usage 462 # render mem usage
401 chart_rect = (off_x, curr_y+30, w, meminfo_bar_h) 463 chart_rect = (off_x, curr_y+30, w, meminfo_bar_h)
402 mem_stats = trace.mem_stats 464 mem_stats = trace.mem_stats
diff --git a/scripts/pybootchartgui/pybootchartgui/parsing.py b/scripts/pybootchartgui/pybootchartgui/parsing.py
index 48eb048dae..301145ab67 100644
--- a/scripts/pybootchartgui/pybootchartgui/parsing.py
+++ b/scripts/pybootchartgui/pybootchartgui/parsing.py
@@ -48,6 +48,7 @@ class Trace:
48 self.filename = None 48 self.filename = None
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.times = [] # Always empty, but expected by draw.py when drawing system charts. 52 self.times = [] # Always empty, but expected by draw.py when drawing system charts.
52 53
53 if len(paths): 54 if len(paths):
@@ -506,6 +507,29 @@ def _parse_proc_meminfo_log(file):
506 507
507 return mem_stats 508 return mem_stats
508 509
510def _parse_monitor_disk_log(file):
511 """
512 Parse file with information about amount of diskspace used.
513 The format of relevant lines should be: ^volume path: number-of-bytes?
514 """
515 disk_stats = []
516 diskinfo_re = re.compile(r'^(.+):\s*(\d+)$')
517
518 for time, lines in _parse_timed_blocks(file):
519 sample = DiskSpaceSample(time)
520
521 for line in lines:
522 match = diskinfo_re.match(line)
523 if not match:
524 raise ParseError("Invalid monitor_disk line \"%s\"" % line)
525 sample.add_value(match.group(1), int(match.group(2)))
526
527 if sample.valid():
528 disk_stats.append(sample)
529
530 return disk_stats
531
532
509# if we boot the kernel with: initcall_debug printk.time=1 we can 533# if we boot the kernel with: initcall_debug printk.time=1 we can
510# get all manner of interesting data from the dmesg output 534# get all manner of interesting data from the dmesg output
511# We turn this into a pseudo-process tree: each event is 535# We turn this into a pseudo-process tree: each event is
@@ -684,6 +708,8 @@ def _do_parse(writer, state, filename, file):
684 state.mem_stats = _parse_proc_meminfo_log(file) 708 state.mem_stats = _parse_proc_meminfo_log(file)
685 elif name == "cmdline2.log": 709 elif name == "cmdline2.log":
686 state.cmdline = _parse_cmdline_log(writer, file) 710 state.cmdline = _parse_cmdline_log(writer, file)
711 elif name == "monitor_disk.log":
712 state.monitor_disk = _parse_monitor_disk_log(file)
687 elif not filename.endswith('.log'): 713 elif not filename.endswith('.log'):
688 _parse_bitbake_buildstats(writer, state, filename, file) 714 _parse_bitbake_buildstats(writer, state, filename, file)
689 t2 = clock() 715 t2 = clock()
diff --git a/scripts/pybootchartgui/pybootchartgui/samples.py b/scripts/pybootchartgui/pybootchartgui/samples.py
index 015d743aa0..bedca4165a 100644
--- a/scripts/pybootchartgui/pybootchartgui/samples.py
+++ b/scripts/pybootchartgui/pybootchartgui/samples.py
@@ -53,6 +53,17 @@ class MemSample:
53 # discard incomplete samples 53 # discard incomplete samples
54 return [v for v in MemSample.used_values if v not in keys] == [] 54 return [v for v in MemSample.used_values if v not in keys] == []
55 55
56class DiskSpaceSample:
57 def __init__(self, time):
58 self.time = time
59 self.records = {}
60
61 def add_value(self, name, value):
62 self.records[name] = value
63
64 def valid(self):
65 return bool(self.records)
66
56class ProcessSample: 67class ProcessSample:
57 def __init__(self, time, state, cpu_sample): 68 def __init__(self, time, state, cpu_sample):
58 self.time = time 69 self.time = time