summaryrefslogtreecommitdiffstats
path: root/scripts/pybootchartgui/pybootchartgui/parsing.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/pybootchartgui/pybootchartgui/parsing.py')
-rw-r--r--scripts/pybootchartgui/pybootchartgui/parsing.py63
1 files changed, 57 insertions, 6 deletions
diff --git a/scripts/pybootchartgui/pybootchartgui/parsing.py b/scripts/pybootchartgui/pybootchartgui/parsing.py
index b42dac6b88..72a54c6ba5 100644
--- a/scripts/pybootchartgui/pybootchartgui/parsing.py
+++ b/scripts/pybootchartgui/pybootchartgui/parsing.py
@@ -48,7 +48,11 @@ 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.net_stats = []
51 self.monitor_disk = None 52 self.monitor_disk = None
53 self.cpu_pressure = []
54 self.io_pressure = []
55 self.mem_pressure = []
52 self.times = [] # Always empty, but expected by draw.py when drawing system charts. 56 self.times = [] # Always empty, but expected by draw.py when drawing system charts.
53 57
54 if len(paths): 58 if len(paths):
@@ -128,7 +132,7 @@ class Trace:
128 def compile(self, writer): 132 def compile(self, writer):
129 133
130 def find_parent_id_for(pid): 134 def find_parent_id_for(pid):
131 if pid is 0: 135 if pid == 0:
132 return 0 136 return 0
133 ppid = self.parent_map.get(pid) 137 ppid = self.parent_map.get(pid)
134 if ppid: 138 if ppid:
@@ -454,7 +458,7 @@ def _parse_proc_disk_stat_log(file):
454 not sda1, sda2 etc. The format of relevant lines should be: 458 not sda1, sda2 etc. The format of relevant lines should be:
455 {major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq} 459 {major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq}
456 """ 460 """
457 disk_regex_re = re.compile ('^([hsv]d.|mtdblock\d|mmcblk\d|cciss/c\d+d\d+.*)$') 461 disk_regex_re = re.compile (r'^([hsv]d.|mtdblock\d|mmcblk\d|cciss/c\d+d\d+.*)$')
458 462
459 # this gets called an awful lot. 463 # this gets called an awful lot.
460 def is_relevant_line(linetokens): 464 def is_relevant_line(linetokens):
@@ -555,6 +559,44 @@ def _parse_monitor_disk_log(file):
555 return disk_stats 559 return disk_stats
556 560
557 561
562def _parse_reduced_net_log(file):
563 net_stats = {}
564 for time, lines in _parse_timed_blocks(file):
565
566 for line in lines:
567 parts = line.split()
568 iface = parts[0][:-1]
569 if iface not in net_stats:
570 net_stats[iface] = [NetSample(time, iface, int(parts[1]), int(parts[2]), int(parts[3]), int(parts[4]))]
571 else:
572 net_stats[iface].append(NetSample(time, iface, int(parts[1]), int(parts[2]), int(parts[3]), int(parts[4])))
573 return net_stats
574
575
576def _parse_pressure_logs(file, filename):
577 """
578 Parse file for "some" pressure with 'avg10', 'avg60' 'avg300' and delta total values
579 (in that order) directly stored on one line for both CPU and IO, based on filename.
580 """
581 pressure_stats = []
582 if filename == "cpu.log":
583 SamplingClass = CPUPressureSample
584 elif filename == "memory.log":
585 SamplingClass = MemPressureSample
586 else:
587 SamplingClass = IOPressureSample
588 for time, lines in _parse_timed_blocks(file):
589 for line in lines:
590 if not line: continue
591 tokens = line.split()
592 avg10 = float(tokens[0])
593 avg60 = float(tokens[1])
594 avg300 = float(tokens[2])
595 delta = float(tokens[3])
596 pressure_stats.append(SamplingClass(time, avg10, avg60, avg300, delta))
597
598 return pressure_stats
599
558# if we boot the kernel with: initcall_debug printk.time=1 we can 600# if we boot the kernel with: initcall_debug printk.time=1 we can
559# get all manner of interesting data from the dmesg output 601# get all manner of interesting data from the dmesg output
560# We turn this into a pseudo-process tree: each event is 602# We turn this into a pseudo-process tree: each event is
@@ -568,8 +610,8 @@ def _parse_monitor_disk_log(file):
568# [ 0.039993] calling migration_init+0x0/0x6b @ 1 610# [ 0.039993] calling migration_init+0x0/0x6b @ 1
569# [ 0.039993] initcall migration_init+0x0/0x6b returned 1 after 0 usecs 611# [ 0.039993] initcall migration_init+0x0/0x6b returned 1 after 0 usecs
570def _parse_dmesg(writer, file): 612def _parse_dmesg(writer, file):
571 timestamp_re = re.compile ("^\[\s*(\d+\.\d+)\s*]\s+(.*)$") 613 timestamp_re = re.compile (r"^\[\s*(\d+\.\d+)\s*]\s+(.*)$")
572 split_re = re.compile ("^(\S+)\s+([\S\+_-]+) (.*)$") 614 split_re = re.compile (r"^(\S+)\s+([\S\+_-]+) (.*)$")
573 processMap = {} 615 processMap = {}
574 idx = 0 616 idx = 0
575 inc = 1.0 / 1000000 617 inc = 1.0 / 1000000
@@ -614,7 +656,7 @@ def _parse_dmesg(writer, file):
614# print "foo: '%s' '%s' '%s'" % (type, func, rest) 656# print "foo: '%s' '%s' '%s'" % (type, func, rest)
615 if type == "calling": 657 if type == "calling":
616 ppid = kernel.pid 658 ppid = kernel.pid
617 p = re.match ("\@ (\d+)", rest) 659 p = re.match (r"\@ (\d+)", rest)
618 if p is not None: 660 if p is not None:
619 ppid = float (p.group(1)) // 1000 661 ppid = float (p.group(1)) // 1000
620# print "match: '%s' ('%g') at '%s'" % (func, ppid, time_ms) 662# print "match: '%s' ('%g') at '%s'" % (func, ppid, time_ms)
@@ -716,7 +758,7 @@ def get_num_cpus(headers):
716 cpu_model = headers.get("system.cpu") 758 cpu_model = headers.get("system.cpu")
717 if cpu_model is None: 759 if cpu_model is None:
718 return 1 760 return 1
719 mat = re.match(".*\\((\\d+)\\)", cpu_model) 761 mat = re.match(r".*\\((\\d+)\\)", cpu_model)
720 if mat is None: 762 if mat is None:
721 return 1 763 return 1
722 return max (int(mat.group(1)), 1) 764 return max (int(mat.group(1)), 1)
@@ -741,6 +783,15 @@ def _do_parse(writer, state, filename, file):
741 state.cmdline = _parse_cmdline_log(writer, file) 783 state.cmdline = _parse_cmdline_log(writer, file)
742 elif name == "monitor_disk.log": 784 elif name == "monitor_disk.log":
743 state.monitor_disk = _parse_monitor_disk_log(file) 785 state.monitor_disk = _parse_monitor_disk_log(file)
786 elif name == "reduced_proc_net.log":
787 state.net_stats = _parse_reduced_net_log(file)
788 #pressure logs are in a subdirectory
789 elif name == "cpu.log":
790 state.cpu_pressure = _parse_pressure_logs(file, name)
791 elif name == "io.log":
792 state.io_pressure = _parse_pressure_logs(file, name)
793 elif name == "memory.log":
794 state.mem_pressure = _parse_pressure_logs(file, name)
744 elif not filename.endswith('.log'): 795 elif not filename.endswith('.log'):
745 _parse_bitbake_buildstats(writer, state, filename, file) 796 _parse_bitbake_buildstats(writer, state, filename, file)
746 t2 = time.process_time() 797 t2 = time.process_time()